-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #200 from pyiron/solutes
- Loading branch information
Showing
5 changed files
with
1,861 additions
and
3 deletions.
There are no files selected for viewing
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
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 | ||
} |
Oops, something went wrong.