Skip to content

Commit

Permalink
Add an example for solute-GB binding
Browse files Browse the repository at this point in the history
  • Loading branch information
liamhuber committed May 16, 2023
1 parent 411b774 commit 0ffe468
Show file tree
Hide file tree
Showing 2 changed files with 1,811 additions and 0 deletions.
164 changes: 164 additions & 0 deletions notebooks/binding_energy.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "98fd7dae-4280-4060-9865-a8179bb0a571",
"metadata": {},
"source": [
"# Example: solute-grain boundary binding\n",
"\n",
"This saved workflow demonstrates how solute-grain boundary (GB) binding can be calculated in ironflow.\n",
"\n",
"In this case, we'll be examining the per-solute-atom energy cost of moving solutes from the bulk into a particular decoration pattern at the GB. I.e.\n",
"\n",
"$E_\\mathrm{bind}^{X}$ = (E_\\mathrm{GB}^X + \\eta E_\\mathrm{bulk}) - (E_\\mathrm{GB} + \\eta E_\\mathrm{bulk}^X)$\n",
"\n",
"Where $X$ denotes the presence of the solute species, bulk and GB denote the structure, and $\\eta$ is the ratio of solute atoms found in the GB structure (2 in the saved workflow below) and the bulk structure (1 in the saved workflow below)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "03fb59eb-db0c-42a9-b315-2230abe9c334",
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"from ironflow import GUI, node_tools as nt\n",
"from pyiron_atomistics import Atoms"
]
},
{
"cell_type": "markdown",
"id": "97468c30-e93f-450c-9916-f8a2925e7127",
"metadata": {},
"source": [
"We have most of the tools we need to do this calculation already in ironflow, but we'll need to add one final node to take our simulation results and do the math described above.\n",
"\n",
"We'll define that node here in the notebook, then register it with ironflow when we instantiate the GUI."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "55b41883-d9cb-46f0-ac57-90423ed67186",
"metadata": {},
"outputs": [],
"source": [
"class BindingEnergy_Node(nt.DataNode):\n",
" \"\"\"\n",
" The average (per-solute) energy associated with moving $n$ solutes from the bulk \n",
" into a particular decoration pattern at a grain boundary.\n",
" \"\"\"\n",
" \n",
" title = \"BindingEnergy\"\n",
" init_inputs = [\n",
" nt.NodeInputBP(label=\"bulk_en\", dtype=nt.dtypes.Float()),\n",
" nt.NodeInputBP(label=\"bulk_x_en\", dtype=nt.dtypes.Float()),\n",
" nt.NodeInputBP(label=\"gb_en\", dtype=nt.dtypes.Float()),\n",
" nt.NodeInputBP(label=\"gb_x_en\", dtype=nt.dtypes.Float()),\n",
" nt.NodeInputBP(\n",
" label=\"bulk_x_structure\",\n",
" dtype=nt.dtypes.Data(valid_classes=[Atoms])\n",
" ),\n",
" nt.NodeInputBP(\n",
" label=\"gb_x_structure\", \n",
" dtype=nt.dtypes.Data(valid_classes=[Atoms])\n",
" ),\n",
" nt.NodeInputBP(label=\"solute_species\", dtype=nt.dtypes.String(default=None)),\n",
" ]\n",
" init_outputs = [\n",
" nt.NodeOutputBP(label=\"binding_energy\", dtype=nt.dtypes.Float())\n",
" ]\n",
" \n",
" def node_function(\n",
" self, \n",
" bulk_en, \n",
" bulk_x_en, \n",
" gb_en, gb_x_en, \n",
" bulk_x_structure, \n",
" gb_x_structure, \n",
" solute_species\n",
" ):\n",
" n_solutes_in_bulk = (bulk_x_structure.get_chemical_symbols() == solute_species).sum()\n",
" n_solutes_at_gb = (gb_x_structure.get_chemical_symbols() == solute_species).sum()\n",
" bulks_per_gb = n_solutes_at_gb / n_solutes_in_bulk\n",
" \n",
" segregated_energy = gb_x_en + bulks_per_gb * bulk_en\n",
" clean_energy = gb_en + bulks_per_gb * bulk_x_en\n",
" return {\"binding_energy\": (segregated_energy - clean_energy) / n_solutes_at_gb}"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5d198f4f-584f-4666-bedf-2a815a0a68e7",
"metadata": {},
"outputs": [],
"source": [
"gui = GUI('solute_gb_binding', extra_nodes_packages=[[BindingEnergy_Node]])"
]
},
{
"cell_type": "markdown",
"id": "7daed9e3-6911-4fa3-8304-6b2b6fe41620",
"metadata": {},
"source": [
"The workflow graph is all ready to go; calculation nodes that run an underyling pyiron job are \"slow\", i.e., unlike the \"fast\" `DataNode` nodes, they need to explicitly receive a `run` command to produce output. Here we've chained them together by connecting their `ran` output signal port to the next calculations `run` input port -- so just hit `run` on the pure bulk structure and the rest will go!\n",
"\n",
"Zoom out with the negative magnifying glass button twice to see the whole workflow at once."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1a29a816-1f3a-402d-a5d1-c8219f03f0ed",
"metadata": {},
"outputs": [],
"source": [
"gui.draw()"
]
},
{
"cell_type": "markdown",
"id": "b55c4bb1-3e4d-4b41-aa56-6af358894821",
"metadata": {},
"source": [
"If you want to modify the calculation, e.g. to change the solute species, don't forget to `reset` each of the minimization nodes.\n",
"\n",
"As an exercise, you may wish to change the host species, or the GB being looked at -- perhaps changing the GB character, or maybe inserting a `Repeat` node before adding solutes to look at the dilute segregation energy. This is possible, but note that the decoration pattern is defined by the `InputArray` node used to define the `indices` for species change -- if you make any changes to the GB in question, you'll need to examine it (click `SHOW` and look at the `plot3d`) and choose new indices for your desired decoration pattern (clicking on individual atoms in the NGLView presentation of the structure shows their index, sometimes with a `^` character breaking up the number, i.e. `4^2` is `42`).\n",
"\n",
"Note that the `Lammps` node normally automatically populates its `potential` input based on its `structure`. In this case, we want to make sure that both the bulk and solute-containing calculations use the _same potential_ in order to get equivalent representations of the host species. To accomplish this, we just manually select a potential from the `LammpsPotentials` node after giving it one of the _solute containing_ structures."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ac20b798-3113-44c8-82b2-1d2cc0ee9aac",
"metadata": {},
"outputs": [],
"source": []
}
],
"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.0"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading

0 comments on commit 0ffe468

Please sign in to comment.