diff --git a/other/materials_designer/Introduction.ipynb b/other/materials_designer/Introduction.ipynb index c54e30a7..8568b4c3 100644 --- a/other/materials_designer/Introduction.ipynb +++ b/other/materials_designer/Introduction.ipynb @@ -62,6 +62,7 @@ "\n", "### 3.3. Planar Defects\n", "#### [3.3.1. Grain Boundary in a 3D Crystal](create_grain_boundary_crystal.ipynb)\n", + "#### [3.3.2. Grain Boundary in a 2D Material](create_grain_boundary_film.ipynb)\n", "\n", "\n", "## 4. Passivation.\n", diff --git a/other/materials_designer/create_grain_boundary_film.ipynb b/other/materials_designer/create_grain_boundary_film.ipynb new file mode 100644 index 00000000..cab9e8c7 --- /dev/null +++ b/other/materials_designer/create_grain_boundary_film.ipynb @@ -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", + "

Usage

\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", + "\"Edge\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 +}