-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create input sockets and links for items inside a dynamic socket (#381)
In AiiDA, one can define a dynamic namespace for the process, which allows the user to pass any nested dictionary with AiiDA data nodes as values. However, in the `WorkGraph`, we need to define the input and output sockets explicitly, so that one can make a link between tasks. To address this discrepancy, and still allow user to pass any nested dictionary with AiiDA data nodes, as well as the output sockets of other tasks, we automatically create the input for each item in the dictionary if the input is not defined. Besides, if the value of the item is a socket, we will link the socket to the task, and remove the item from the dictionary.
- Loading branch information
1 parent
02e1c48
commit c08af7a
Showing
13 changed files
with
873 additions
and
41 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"id": "22d177dc-6cfb-4de2-9509-f1eb45e10cf2", | ||
"metadata": {}, | ||
"source": [ | ||
"# Use `CalcJob` and `WorkChain` insdie WorkGraph\n", | ||
"One can use `CalcJob`, `WorkChain` and other AiiDA components direclty in the WorkGraph. The inputs and outputs of the task is automatically generated based on the input and output port of the AiiDA component." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"id": "a6e0038f", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/html": [ | ||
"\n", | ||
" <iframe\n", | ||
" width=\"100%\"\n", | ||
" height=\"600px\"\n", | ||
" src=\"html/test_use_calcjob.html\"\n", | ||
" frameborder=\"0\"\n", | ||
" allowfullscreen\n", | ||
" \n", | ||
" ></iframe>\n", | ||
" " | ||
], | ||
"text/plain": [ | ||
"<IPython.lib.display.IFrame at 0x7329bd9dca90>" | ||
] | ||
}, | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"\n", | ||
"from aiida_workgraph import WorkGraph\n", | ||
"from aiida.calculations.arithmetic.add import ArithmeticAddCalculation\n", | ||
"\n", | ||
"wg = WorkGraph(\"test_use_calcjob\")\n", | ||
"task1 = wg.add_task(ArithmeticAddCalculation, name=\"add1\")\n", | ||
"task2 = wg.add_task(ArithmeticAddCalculation, name=\"add2\", x=wg.tasks[\"add1\"].outputs[\"sum\"])\n", | ||
"wg.to_html()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "1781a459", | ||
"metadata": {}, | ||
"source": [ | ||
"## Set inputs\n", | ||
"One can set the inputs when adding the task, or using the `set` method of the `Task` object." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 5, | ||
"id": "288327e4", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from aiida import load_profile\n", | ||
"from aiida.orm import Int\n", | ||
"\n", | ||
"load_profile()\n", | ||
"\n", | ||
"# use set method\n", | ||
"task1.set({\"x\": Int(1), \"y\": Int(2)})\n", | ||
"# set the inputs when adding the task\n", | ||
"task3 = wg.add_task(ArithmeticAddCalculation, name=\"add3\", x=Int(3), y=Int(4))\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "ef4ba444", | ||
"metadata": {}, | ||
"source": [ | ||
"### Use process builder\n", | ||
"One can also set the inputs of the task using the process builder." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 4, | ||
"id": "53e31346", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"\n", | ||
"from aiida.calculations.arithmetic.add import ArithmeticAddCalculation\n", | ||
"from aiida.orm import Int, load_code\n", | ||
"\n", | ||
"\n", | ||
"code = load_code(\"add@localhost\")\n", | ||
"builder = ArithmeticAddCalculation.get_builder()\n", | ||
"builder.code = code\n", | ||
"builder.x = Int(2)\n", | ||
"builder.y = Int(3)\n", | ||
"\n", | ||
"wg = WorkGraph(\"test_set_inputs_from_builder\")\n", | ||
"add1 = wg.add_task(ArithmeticAddCalculation, name=\"add1\")\n", | ||
"add1.set_from_builder(builder)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "a0a1dbf0", | ||
"metadata": {}, | ||
"source": [ | ||
"\n", | ||
"## Dynamic namespace\n", | ||
"In AiiDA, one can define a dynamic namespace for the process, which allows the user to pass any nested dictionary with AiiDA data nodes as values. However, in the `WorkGraph`, we need to define the input and output sockets explicitly, so that one can make a link between tasks. To address this discrepancy, and still allow user to pass any nested dictionary with AiiDA data nodes, as well as the output sockets of other tasks, we automatically create the input for each item in the dictionary if the input is not defined. Besides, if the value of the item is a socket, we will link the socket to the task, and remove the item from the dictionary.\n", | ||
"\n", | ||
"For example, the `WorkChainWithDynamicNamespace` has a dynamic namespace `dynamic_port`, and the user can pass any nested dictionary as the input.\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 8, | ||
"id": "4a81efa9", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"Failed to inspect function WorkChainWithDynamicNamespace: source code not available\n" | ||
] | ||
}, | ||
{ | ||
"data": { | ||
"text/html": [ | ||
"\n", | ||
" <iframe\n", | ||
" width=\"100%\"\n", | ||
" height=\"600px\"\n", | ||
" src=\"html/test_dynamic_namespace.html\"\n", | ||
" frameborder=\"0\"\n", | ||
" allowfullscreen\n", | ||
" \n", | ||
" ></iframe>\n", | ||
" " | ||
], | ||
"text/plain": [ | ||
"<IPython.lib.display.IFrame at 0x77b0e0b96f90>" | ||
] | ||
}, | ||
"execution_count": 8, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"from aiida.engine import WorkChain\n", | ||
"\n", | ||
"class WorkChainWithDynamicNamespace(WorkChain):\n", | ||
" \"\"\"WorkChain with dynamic namespace.\"\"\"\n", | ||
"\n", | ||
" @classmethod\n", | ||
" def define(cls, spec):\n", | ||
" \"\"\"Specify inputs and outputs.\"\"\"\n", | ||
" super().define(spec)\n", | ||
" spec.input_namespace(\"dynamic_port\", dynamic=True)\n", | ||
"\n", | ||
"wg = WorkGraph(\"test_dynamic_namespace\")\n", | ||
"task1 = wg.add_task(ArithmeticAddCalculation, name=\"add1\")\n", | ||
"task2 = wg.add_task(\n", | ||
" WorkChainWithDynamicNamespace,\n", | ||
" dynamic_port={\n", | ||
" \"input1\": None,\n", | ||
" \"input2\": Int(2),\n", | ||
" \"input3\": task1.outputs[\"sum\"],\n", | ||
" },\n", | ||
" )\n", | ||
"wg.to_html()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "015f91d7", | ||
"metadata": {}, | ||
"source": [ | ||
"## Summary\n", | ||
"\n", | ||
"In this example, we will show how to use `CalcJob` and `WorkChain` inside the WorkGraph. One can also use `WorkGraph` inside a `WorkChain`, please refer to the [Calling WorkGraph within a WorkChain](workchain_call_workgraph.ipynb) for more details." | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "aiida", | ||
"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.0" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 5 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.