-
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 #166 from Exabyte-io/feature/SOF-7497
feature/SOF-7497 feat: 2D material grain boundary NB
- Loading branch information
Showing
2 changed files
with
323 additions
and
0 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
322 changes: 322 additions & 0 deletions
322
other/materials_designer/create_grain_boundary_film.ipynb
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,322 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"# Create a 2D Surface Grain Boundary in a film\n", | ||
"\n", | ||
"Use commensurate lattice matching algorithm to create grain boundaries in 2D materials by finding appropriate twist angles between two orientations of the same material.\n", | ||
"\n", | ||
"<h2 style=\"color:green\">Usage</h2>\n", | ||
"\n", | ||
"1. Make sure to select Input Material (in the outer runtime) before running the notebook.\n", | ||
"1. Set notebook parameters in cell 1.1. below (or use the default values).\n", | ||
"1. Click \"Run\" > \"Run All\" to run all cells.\n", | ||
"1. Wait for the run to complete (depending on the parameters can take a few min).\n", | ||
"1. Scroll down to view results.\n", | ||
"\n", | ||
"## Notes\n", | ||
"\n", | ||
"1. We perform commensurate lattice matching to find valid supercells that achieve the desired twist angle.\n", | ||
"1. When the matching is finished, grain boundaries with angles close to the target are presented.\n", | ||
"1. The algorithm searches for supercell matrices within specified size limits.\n", | ||
"2. The two orientations are placed next to each other in the x-direction with a gap in between.\n", | ||
"1. Atoms on the edge of the left orientation are handled to overlap with the right orientation in the interfacial region.\n", | ||
"1. For more information, see the [Introduction](Introduction.ipynb) notebook.\n" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "415ed707e27a6c8e" | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"## 1. Prepare the Environment\n", | ||
"### 1.1. Set up the notebook\n", | ||
"Set the following flags to control the notebook behavior\n", | ||
"For more information on the parameters and algorithm, refer to [Grain Boundary Builder Source](https://github.com/Exabyte-io/made/blob/35b9f318f5d667e0f5af023f3178bc4404317ab0/src/py/mat3ra/made/tools/build/grain_boundary/builders.py#L103)\n", | ||
"`EDGE_INCLUSION_TOLERANCE` is a fine-tuning parameter that controls the inclusion of the edge atoms for both orientations in the gap.\n", | ||
"For example of Graphene at 17.9 degrees: orange and green atoms are present with the value of 0.5 Angstroms, with value of 0, they will not be included.\n", | ||
"<img src=\"https://i.imgur.com/QRgotXS.png\" alt=\"Edge Inclusion Tolerance\" width=\"400\"/>\n" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "a080006df3785cc5" | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"outputs": [], | ||
"source": [ | ||
"# Material selection\n", | ||
"MATERIAL_INDEX = 0 # Index in the list of materials\n", | ||
"\n", | ||
"# Grain boundary parameters\n", | ||
"TARGET_TWIST_ANGLE = 17.9 # in degrees\n", | ||
"BOUNDARY_GAP = 2.0 # Gap between two orientations in X direction, in Angstroms\n", | ||
"XY_SUPERCELL_MATRIX = [[1, 0], [0, 1]] # Supercell matrix to be applied to each of the orientations before matching\n", | ||
"\n", | ||
"# Search algorithm parameters\n", | ||
"MAX_REPETITION = 6 # Maximum supercell matrix element value\n", | ||
"ANGLE_TOLERANCE = 2.5 # in degrees\n", | ||
"RETURN_FIRST_MATCH = True # If True, returns first solution within tolerance\n", | ||
"\n", | ||
"# Distance tolerance for two atoms to be considered too close. \n", | ||
"# Used when merging two orientations to remove the atoms of the first one. \n", | ||
"# Should be less than the expected bond length\n", | ||
"DISTANCE_TOLERANCE = 1.2 # in Angstroms\n", | ||
"\n", | ||
"# How much to expand inclusion of the edge atoms for both orientations and fill in the gap region.\n", | ||
"# A fine-tuning parameter\n", | ||
"EDGE_INCLUSION_TOLERANCE = 0.5 # in Angstroms\n", | ||
"\n", | ||
"# Visualization parameters\n", | ||
"SHOW_INTERMEDIATE_STEPS = True\n", | ||
"CELL_REPETITIONS_FOR_VISUALIZATION = [3, 3, 1]" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "338ee3c51155e086", | ||
"execution_count": null | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"### 1.2. Install packages\n", | ||
"The step executes only in Pyodide environment. For other environments, the packages should be installed via `pip install`." | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "6463f9bbcd3be7c7" | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"outputs": [], | ||
"source": [ | ||
"import sys\n", | ||
"\n", | ||
"if sys.platform == \"emscripten\":\n", | ||
" import micropip\n", | ||
"\n", | ||
" await micropip.install('mat3ra-api-examples', deps=False)\n", | ||
" from utils.jupyterlite import install_packages\n", | ||
"\n", | ||
" await install_packages(\"\", \"../../config.yml\")" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "7e22d1f4da825575", | ||
"execution_count": null | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"### 1.3. Load and preview input material" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "4a1cfe15caa44c3e" | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"outputs": [], | ||
"source": [ | ||
"from utils.jupyterlite import get_materials\n", | ||
"\n", | ||
"materials = get_materials(globals())" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "a1635c31132962f6", | ||
"execution_count": null | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"## 2. Prepare Material\n", | ||
"### 2.1. Select and visualize initial material" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "32b3ad775543b06f" | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"outputs": [], | ||
"source": [ | ||
"from utils.visualize import visualize_materials\n", | ||
"\n", | ||
"material = materials[MATERIAL_INDEX]\n", | ||
"\n", | ||
"if SHOW_INTERMEDIATE_STEPS:\n", | ||
" visualize_materials(material, repetitions=CELL_REPETITIONS_FOR_VISUALIZATION)" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "61f0870d8104cd21", | ||
"execution_count": null | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"## 3. Generate Surface Grain Boundary\n", | ||
"### 3.1. Set up grain boundary configuration and builder\n" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "34d6c7a337f1e40b" | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"outputs": [], | ||
"source": [ | ||
"from mat3ra.made.tools.build.grain_boundary import (\n", | ||
" SurfaceGrainBoundaryConfiguration,\n", | ||
" SurfaceGrainBoundaryBuilderParameters,\n", | ||
" SurfaceGrainBoundaryBuilder\n", | ||
")\n", | ||
"\n", | ||
"config = SurfaceGrainBoundaryConfiguration(\n", | ||
" film=material,\n", | ||
" twist_angle=TARGET_TWIST_ANGLE,\n", | ||
" distance_z=BOUNDARY_GAP,\n", | ||
" gap=BOUNDARY_GAP,\n", | ||
" xy_supercell_matrix=XY_SUPERCELL_MATRIX\n", | ||
")\n", | ||
"\n", | ||
"params = SurfaceGrainBoundaryBuilderParameters(\n", | ||
" max_supercell_matrix_int=MAX_REPETITION,\n", | ||
" angle_tolerance=ANGLE_TOLERANCE,\n", | ||
" return_first_match=RETURN_FIRST_MATCH,\n", | ||
" edge_inclusion_tolerance=EDGE_INCLUSION_TOLERANCE,\n", | ||
" distance_tolerance=DISTANCE_TOLERANCE\n", | ||
")\n", | ||
"\n", | ||
"builder = SurfaceGrainBoundaryBuilder(build_parameters=params)" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "33a2c8a9be436745", | ||
"execution_count": null | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"### 3.2. Generate and analyze grain boundaries\n" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "79e9378bf5e144d4" | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"outputs": [], | ||
"source": [ | ||
"from utils.plot import plot_twisted_interface_solutions\n", | ||
"\n", | ||
"grain_boundaries = builder.get_materials(config)\n", | ||
"\n", | ||
"print(f\"\\nFound {len(grain_boundaries)} possible structures\")\n", | ||
"for i, gb in enumerate(grain_boundaries):\n", | ||
" actual_angle = gb.metadata.get(\"actual_twist_angle\", \"unknown\")\n", | ||
" print(f\"\\nGrain Boundary {i + 1}:\")\n", | ||
" print(f\"Actual twist angle: {actual_angle}°\")\n", | ||
" print(f\"Number of atoms: {len(gb.basis.elements.ids)}\")\n", | ||
"\n", | ||
"if len(grain_boundaries) > 0:\n", | ||
" plot_twisted_interface_solutions(grain_boundaries)" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "d7007fe825463e5a", | ||
"execution_count": null | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"## 4. Preview the selected grain boundary\n", | ||
"By default, the first grain boundary is selected. You can change the selection by changing the `selected_structure` index." | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "8b2f0574a20089a5" | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"outputs": [], | ||
"source": [ | ||
"selected_structure = grain_boundaries[0]\n", | ||
"actual_angle = selected_structure.metadata.get(\"build\").get(\"configuration\").get(\"actual_twist_angle\")\n", | ||
"print(f\"Target angle: {TARGET_TWIST_ANGLE}°\")\n", | ||
"print(f\"Actual angle: {actual_angle}°\")\n", | ||
"print(f\"Number of atoms: {len(selected_structure.basis.elements.ids)}\")\n", | ||
"\n", | ||
"visualize_materials(selected_structure, repetitions=[1, 1, 1])\n", | ||
"visualize_materials(selected_structure, repetitions=[1, 1, 1], rotation=\"-90x\")" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "7f558a8e9d417cef", | ||
"execution_count": null | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"### 5. Pass data to the outside runtime\n" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "afcc004c5878b56f" | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"outputs": [], | ||
"source": [ | ||
"from utils.jupyterlite import set_materials\n", | ||
"\n", | ||
"set_materials(selected_structure)" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"id": "20e46167358d63", | ||
"execution_count": null | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 2 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython2", | ||
"version": "2.7.6" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 5 | ||
} |