diff --git a/other/materials_designer/specific_examples/grain_boundary_2d_boron_nitride.ipynb b/other/materials_designer/specific_examples/grain_boundary_2d_boron_nitride.ipynb new file mode 100644 index 00000000..7817958e --- /dev/null +++ b/other/materials_designer/specific_examples/grain_boundary_2d_boron_nitride.ipynb @@ -0,0 +1,316 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# A 2D grain boundary in Boron Nitride\n", + "\n", + "## 0. Introduction\n", + "\n", + "This notebook demonstrates how to generate a 2D grain boundary in Boron Nitride, following the example in the manuscript:\n", + "\n", + "> **Qiucheng Li, Xiaolong Zou, Mengxi Liu, Jingyu Sun, Yabo Gao, Yue Qi, Xiebo Zhou, Boris I. Yakobson, Yanfeng Zhang, and Zhongfan Liu**\n", + "> \"Grain Boundary Structures and Electronic Properties of Hexagonal Boron Nitride on Cu(111)\"\n", + "> *ACS Nano* **2015** 9 (6), 6308-6315\n", + "> [DOI: 10.1021/acs.nanolett.5b01852](https://doi.org/10.1021/acs.nanolett.5b01852)\n", + "\n", + "Reproducing the material from Figure 2. c:\n", + "\n", + "\"Grain" + ], + "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_NAME = \"Boron_Nitride\" # Name of the material to import from Standata\n", + "\n", + "# Grain boundary parameters\n", + "TARGET_TWIST_ANGLE = 9.0 # in degrees\n", + "BOUNDARY_GAP = 0.0 # Gap between two orientations in X direction, in Angstroms\n", + "XY_SUPERCELL_MATRIX = [[1, 0], [0, 2]] # Supercell matrix to be applied to each of the orientations before matching\n", + "\n", + "# Search algorithm parameters\n", + "MAX_REPETITION = None # Maximum supercell matrix element value\n", + "ANGLE_TOLERANCE = 0.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.43 # 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.0 # 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(\"specific_examples\")" + ], + "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 mat3ra.standata.materials import Materials\n", + "from mat3ra.made.material import Material\n", + "\n", + "material = Material(Materials.get_by_name_first_match(MATERIAL_NAME))" + ], + "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", + "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", + "\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 download_content_to_file\n", + "\n", + "download_content_to_file(selected_structure, \"grain_boundary_2d_boron_nitride.json\")" + ], + "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 +}