diff --git a/other/materials_designer/specific_examples/interface_2d_2d_boron_nitride_graphene.ipynb b/other/materials_designer/specific_examples/interface_2d_2d_boron_nitride_graphene.ipynb new file mode 100644 index 00000000..9003fd04 --- /dev/null +++ b/other/materials_designer/specific_examples/interface_2d_2d_boron_nitride_graphene.ipynb @@ -0,0 +1,526 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Interface between 2D materials: Boron Nitride and Graphene\n", + "\n", + "## Introduction\n", + "\n", + "This notebook demonstrates the creation of an interface between two 2D materials, Boron Nitride (BN) and Graphene and shifting the film along the y-axis to create multiple (7) stacking configurations.\n", + "\n", + "Following the manuscript:\n", + "> **Jeil Jung, Ashley M. DaSilva, Allan H. MacDonald & Shaffique Adam**\n", + "> **Origin of the band gap in graphene on hexagonal boron nitride**\n", + "> Nature Communications volume 6, Article number: 6308 (2015)\n", + "> [DOI: 10.1038/ncomms7308](https://doi.org/10.1038/ncomms7308)\n", + "\n", + "\n", + "Relicating the materials with profile give in Figure 7. a (top row):\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## 1. Prepare the Environment\n", + "### 1.1. Set up the notebook \n", + "\n", + "Set the following flags to control the notebook behavior " + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "# Enable interactive selection of terminations via UI prompt\n", + "IS_TERMINATIONS_SELECTION_INTERACTIVE = False \n", + "\n", + "FILM_INDEX = 1 # Index in the list of materials, to access as materials[FILM_INDEX]\n", + "FILM_MILLER_INDICES = (0, 0, 1)\n", + "FILM_THICKNESS = 1 # in atomic layers\n", + "FILM_VACUUM = 0.0 # in angstroms\n", + "FILM_XY_SUPERCELL_MATRIX = [[1, 0], [0, 1]]\n", + "FILM_USE_ORTHOGONAL_Z = True\n", + "\n", + "SUBSTRATE_INDEX = 0\n", + "SUBSTRATE_MILLER_INDICES = (0, 0, 1)\n", + "SUBSTRATE_THICKNESS = 1 # in atomic layers\n", + "SUBSTRATE_VACUUM = 0.0 # in angstroms\n", + "SUBSTRATE_XY_SUPERCELL_MATRIX = [[1, 0], [0, 1]]\n", + "SUBSTRATE_USE_ORTHOGONAL_Z = True\n", + "\n", + "# Maximum area for the superlattice search algorithm\n", + "MAX_AREA = 50 # in Angstrom^2\n", + "# Set the termination pair indices\n", + "TERMINATION_PAIR_INDEX = 0 # Will be overridden in interactive selection is used\n", + "INTERFACE_DISTANCE = 3.4 # in Angstrom\n", + "INTERFACE_VACUUM = 20.0 # in Angstrom" + ], + "metadata": { + "collapsed": false + }, + "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` (see [README](../../README.ipynb))." + ], + "metadata": { + "collapsed": false + } + }, + { + "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", + " await install_packages(\"specific_examples|create_interface_with_min_strain_zsl.ipynb\")" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 1.3. Get input materials and assign `substrate` and `film`\n", + "Materials are loaded with `get_data()`. The first material is assigned as substrate and the second as film." + ], + "metadata": {} + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "from mat3ra.standata.materials import Materials\n", + "from mat3ra.made.material import Material\n", + "film = Material(Materials.get_by_name_first_match(\"Graphene\"))\n", + "substrate = Material(Materials.get_by_name_and_categories(\"BN\", \"2D\"))" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 1.4. Preview Substrate and Film" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "from utils.visualize import visualize_materials as visualize\n", + "visualize([substrate, film], repetitions=[3, 3, 1], rotation=\"0x\")" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "## 2. Configure slabs and select termination pair\n", + "\n", + "### 2.1. Create Substrate and Layer Slabs\n", + "Slab Configuration lets define the slab thickness, vacuum, and the Miller indices of the interfacial plane and get the slabs with possible terminations.\n", + "Define the substrate slab cell that will be used as a base for the interface and the film slab cell that will be placed on top of the substrate slab." + ], + "metadata": {} + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "from mat3ra.made.tools.build.slab import SlabConfiguration, get_terminations, create_slab\n", + "\n", + "film_slab_configuration = SlabConfiguration(\n", + " bulk=film,\n", + " miller_indices=FILM_MILLER_INDICES,\n", + " thickness=FILM_THICKNESS, # in atomic layers\n", + " vacuum=FILM_VACUUM, # in angstroms\n", + " xy_supercell_matrix=FILM_XY_SUPERCELL_MATRIX,\n", + " use_orthogonal_z=FILM_USE_ORTHOGONAL_Z\n", + ")\n", + "\n", + "substrate_slab_configuration = SlabConfiguration(\n", + " bulk=substrate,\n", + " miller_indices=SUBSTRATE_MILLER_INDICES,\n", + " thickness=SUBSTRATE_THICKNESS, # in atomic layers\n", + " vacuum=SUBSTRATE_VACUUM, # in angstroms\n", + " xy_supercell_matrix=SUBSTRATE_XY_SUPERCELL_MATRIX,\n", + " use_orthogonal_z=SUBSTRATE_USE_ORTHOGONAL_Z\n", + ")" + ], + "metadata": {}, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 2.2. Get possible terminations for the slabs" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "film_slab_terminations = get_terminations(film_slab_configuration)\n", + "substrate_slab_terminations = get_terminations(substrate_slab_configuration)" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 2.3. Visualize slabs for all possible terminations" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "film_slabs = [create_slab(film_slab_configuration, termination) for termination in film_slab_terminations]\n", + "substrate_slabs = [create_slab(substrate_slab_configuration, termination) for termination in substrate_slab_terminations]\n", + "\n", + "visualize([{\"material\":slab, \"title\": slab.metadata[\"build\"][\"termination\"]} for slab in film_slabs ], repetitions=[3, 3, 1], rotation=\"-90x\")\n", + "visualize([{\"material\":slab, \"title\": slab.metadata[\"build\"][\"termination\"]} for slab in substrate_slabs ], repetitions=[3, 3, 1], rotation=\"-90x\") " + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 2.4. Print terminations for the interface" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "from itertools import product\n", + "\n", + "termination_pairs = list(product(film_slab_terminations, substrate_slab_terminations)) \n", + "print(\"Termination Pairs (Film, Substrate)\")\n", + "for idx, termination_pair in enumerate(termination_pairs):\n", + " print(f\" {idx}: {termination_pair}\")" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 2.5. Select termination pair for the interface" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "from utils.io import ui_prompt_select_array_element_by_index, ui_prompt_select_array_element_by_index_pyodide\n", + "\n", + "termination_pair_index = TERMINATION_PAIR_INDEX\n", + "\n", + "termination_pair = termination_pairs[termination_pair_index]\n", + "if IS_TERMINATIONS_SELECTION_INTERACTIVE:\n", + " if sys.platform == \"emscripten\":\n", + " termination_pair = await ui_prompt_select_array_element_by_index_pyodide(termination_pairs, element_name=\"film/substrate termination pair\")\n", + " else:\n", + " termination_pair = ui_prompt_select_array_element_by_index(termination_pairs, element_name=\"film/substrate termination pair\")" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "## 3. Create interfaces\n", + "\n", + "### 3.1. Initialize the Interface Configuration" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "from mat3ra.made.tools.build.interface import InterfaceConfiguration\n", + "\n", + "film_termination, substrate_termination = termination_pair\n", + "interface_configuration = InterfaceConfiguration(\n", + " film_configuration=film_slab_configuration,\n", + " substrate_configuration=substrate_slab_configuration,\n", + " film_termination=film_termination,\n", + " substrate_termination=substrate_termination,\n", + " distance=INTERFACE_DISTANCE,\n", + " vacuum= INTERFACE_VACUUM\n", + ")" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 3.2. Set Strain Matching Algorithm Parameters (Optional)\n", + "The search algorithm for supercells matching can be tuned by setting its parameters directly, otherwise the default values are used." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "from mat3ra.made.tools.build.interface import ZSLStrainMatchingParameters\n", + "zsl_strain_matching_parameters = ZSLStrainMatchingParameters(\n", + " max_area=MAX_AREA\n", + ")" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 3.3. Generate interfaces with strain matcher\n", + "Interfaces are sorted by size and strain." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "from mat3ra.made.tools.build.interface import ZSLStrainMatchingInterfaceBuilder, ZSLStrainMatchingInterfaceBuilderParameters\n", + "\n", + "matched_interfaces_builder = ZSLStrainMatchingInterfaceBuilder(build_parameters=ZSLStrainMatchingInterfaceBuilderParameters(strain_matching_parameters=zsl_strain_matching_parameters))\n", + "\n", + "interfaces_sorted_by_size_and_strain= matched_interfaces_builder.get_materials(configuration=interface_configuration)" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 3.4. Plot interfaces by size and strain\n" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "from utils.plot import plot_strain_vs_atoms\n", + "\n", + "PLOT_SETTINGS = {\n", + " \"HEIGHT\": 600,\n", + " \"X_SCALE\": \"log\", # or linear\n", + " \"Y_SCALE\": \"log\", # or linear\n", + "}\n", + "\n", + "plot_strain_vs_atoms(interfaces_sorted_by_size_and_strain, PLOT_SETTINGS)" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 3.5. Select the interface\n", + "\n", + "Select the index for the interface with the lowest strain and the smallest number of atoms." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "# select the first interface with the lowest strain and the smallest number of atoms\n", + "interfaces_slice_range_or_index = 0\n", + "selected_interface = interfaces_sorted_by_size_and_strain[interfaces_slice_range_or_index]" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 4.1 Preview the selected material" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "visualize(selected_interface, repetitions=[3, 3, 1])\n", + "visualize(selected_interface, repetitions=[3, 3, 1], rotation=\"-90x\")" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 4.2. Shift film along y-axis\n", + "Shifting with the step of a/sqrt(3)/2 angstroms, where a is the lattice constant of the interface." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "import numpy as np\n", + "from mat3ra.made.tools.modify import interface_displace_part\n", + "a = selected_interface.lattice.a\n", + "shifted_interfaces = []\n", + "for n in range(7):\n", + " shifted_interface= interface_displace_part(selected_interface, [0,n*a/np.sqrt(3)/2,0], use_cartesian_coordinates=True)\n", + " shifted_interfaces.append(shifted_interface)" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 4.3. Preview the shifted materials" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "visualize(shifted_interfaces, repetitions=[3, 3, 1])" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5. Pass data to the outside runtime" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from utils.jupyterlite import download_content_to_file\n", + "for idx, interface in enumerate(shifted_interfaces):\n", + " download_content_to_file(interface, f\"interface_{idx}.json\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.10.12" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}