Skip to content

Feature/SOF-7338 update: adjust other NBs to use made-tools #119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 45 additions & 199 deletions other/materials_designer/create_interface_with_relaxation_ase_emt.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,11 @@
"outputs": [],
"source": [
"SUBSTRATE_PARAMETERS = {\n",
" \"MATERIAL_INDEX\": 0, # the index of the material in the materials_in list\n",
" \"MILLER_INDICES\": (1, 1, 1), # the miller indices of the interfacial plane\n",
" \"THICKNESS\": 3, # in layers\n",
"}\n",
"\n",
"LAYER_PARAMETERS = {\n",
" \"MATERIAL_INDEX\": 1, # the index of the material in the materials_in list\n",
" \"MILLER_INDICES\": (0, 0, 1), # the miller indices of the interfacial plane\n",
" \"THICKNESS\": 1, # in layers\n",
"}\n",
Expand Down Expand Up @@ -113,7 +111,8 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Install Packages\n"
"## 2. Install Packages\n",
"The step executes only in Pyodide environment. For other environments, the packages should be installed via `pip install` as directed in README.\n"
]
},
{
Expand All @@ -126,8 +125,8 @@
"if sys.platform == \"emscripten\":\n",
" import micropip\n",
" await micropip.install('mat3ra-api-examples', deps=False)\n",
"from utils.jupyterlite import install_packages\n",
"await install_packages(\"create_interface_with_min_strain_zsl.ipynb\",\"../../config.yml\")"
" from utils.jupyterlite import install_packages\n",
" await install_packages(\"create_interface_with_min_strain_zsl.ipynb\",\"../../config.yml\")"
]
},
{
Expand All @@ -144,23 +143,19 @@
"outputs": [],
"source": [
"from utils.jupyterlite import get_data\n",
"from pymatgen.analysis.structure_analyzer import SpacegroupAnalyzer\n",
"from src.utils import to_pymatgen\n",
"from mat3ra.made.material import Material\n",
"\n",
"# Get the list of input materials and load them into `materials_in` variable\n",
"get_data(\"materials_in\", globals())\n",
"\n",
"if \"materials_in\" in globals():\n",
" pymatgen_materials = [to_pymatgen(item) for item in materials_in]\n",
" if USE_CONVENTIONAL_CELL: pymatgen_materials = [SpacegroupAnalyzer(item).get_conventional_standard_structure() for\n",
" item in pymatgen_materials]\n",
"\n",
" for material in pymatgen_materials:\n",
" print(material, \"\\n\")"
"materials = [] \n",
"for material in globals()[\"materials_in\"]:\n",
" print(material, \"\\n\")\n",
" materials.append(Material(material))"
],
"metadata": {
"collapsed": false
}
},
"execution_count": null
},
{
"cell_type": "markdown",
Expand All @@ -182,58 +177,18 @@
},
"outputs": [],
"source": [
"from src.pymatgen_coherent_interface_builder import CoherentInterfaceBuilder, ZSLGenerator\n",
"from src.utils import translate_to_bottom\n",
"\n",
"# Translate the materials to the bottom of the cell to allow for multilayer heterostructures creation\n",
"pymatgen_materials = [translate_to_bottom(item) for item in pymatgen_materials]\n",
"\n",
"def create_interfaces(settings: dict):\n",
" print(\"Creating interfaces...\")\n",
" zsl = ZSLGenerator(\n",
" max_area_ratio_tol=settings[\"ZSL_PARAMETERS\"][\"MAX_AREA_TOL\"],\n",
" max_area=settings[\"ZSL_PARAMETERS\"][\"MAX_AREA\"],\n",
" max_length_tol=settings[\"ZSL_PARAMETERS\"][\"MAX_LENGTH_TOL\"],\n",
" max_angle_tol=settings[\"ZSL_PARAMETERS\"][\"MAX_ANGLE_TOL\"],\n",
" )\n",
"\n",
" cib = CoherentInterfaceBuilder(\n",
" substrate_structure=pymatgen_materials[settings[\"SUBSTRATE_PARAMETERS\"][\"MATERIAL_INDEX\"]],\n",
" film_structure=pymatgen_materials[settings[\"LAYER_PARAMETERS\"][\"MATERIAL_INDEX\"]],\n",
" substrate_miller=settings[\"SUBSTRATE_PARAMETERS\"][\"MILLER_INDICES\"],\n",
" film_miller=settings[\"LAYER_PARAMETERS\"][\"MILLER_INDICES\"],\n",
" zslgen=zsl,\n",
" strain_tol=settings[\"ZSL_PARAMETERS\"][\"STRAIN_TOL\"],\n",
" )\n",
"\n",
" # Find terminations\n",
" cib._find_terminations()\n",
" terminations = cib.terminations\n",
"\n",
" # Create interfaces for each termination\n",
" interfaces = {}\n",
" for termination in terminations:\n",
" interfaces[termination] = []\n",
" for interface in cib.get_interfaces(\n",
" termination,\n",
" gap=settings[\"INTERFACE_PARAMETERS\"][\"DISTANCE_Z\"],\n",
" film_thickness=settings[\"LAYER_PARAMETERS\"][\"THICKNESS\"],\n",
" substrate_thickness=settings[\"SUBSTRATE_PARAMETERS\"][\"THICKNESS\"],\n",
" in_layers=True,\n",
" ):\n",
" # Wrap atoms to unit cell\n",
" interface[\"interface\"].make_supercell((1, 1, 1), to_unit_cell=True)\n",
" interfaces[termination].append(interface)\n",
" return interfaces, terminations\n",
"\n",
"\n",
"interfaces, terminations = create_interfaces(\n",
"from mat3ra.made.tools.build import create_interfaces\n",
"\n",
"interface_data_holder = create_interfaces(\n",
" materials[0],\n",
" materials[1],\n",
" settings={\n",
" \"SUBSTRATE_PARAMETERS\": SUBSTRATE_PARAMETERS,\n",
" \"LAYER_PARAMETERS\": LAYER_PARAMETERS,\n",
" \"USE_CONVENTIONAL_CELL\": USE_CONVENTIONAL_CELL,\n",
" \"ZSL_PARAMETERS\": ZSL_PARAMETERS,\n",
" \"INTERFACE_PARAMETERS\": INTERFACE_PARAMETERS,\n",
" }\n",
" },\n",
")\n"
]
},
Expand All @@ -250,68 +205,15 @@
"metadata": {},
"outputs": [],
"source": [
"print(f'Found {len(terminations)} terminations')\n",
"for termination in terminations:\n",
" print(f\"Found {len(interfaces[termination])} interfaces for\", termination, \"termination\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Sort interfaces by strain\n",
"\n",
"### 5.1. Sort all interfaces\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Could be \"strain\", \"von_mises_strain\", \"mean_abs_strain\"\n",
"strain_mode = \"mean_abs_strain\"\n",
"\n",
"\n",
"# Sort interfaces by the specified strain mode and number of sites\n",
"def sort_interfaces(interfaces, terminations):\n",
" sorted_interfaces = {}\n",
" for termination in terminations:\n",
" sorted_interfaces[termination] = sorted(\n",
" interfaces[termination], key=lambda x: (x[strain_mode], x[\"interface\"].num_sites)\n",
" )\n",
" return sorted_interfaces\n",
"\n",
"\n",
"sorted_interfaces = sort_interfaces(interfaces, terminations)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 5.2. Print out interfaces with lowest strain for each termination\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for termination in terminations:\n",
" print(f\"Interface with lowest strain for termination {termination} (index 0):\")\n",
" first_interface = interfaces[termination][0]\n",
" print(\" strain:\", first_interface[strain_mode] * 100, \"%\")\n",
" print(\" number of atoms:\", first_interface[\"interface\"].num_sites)"
"print(interface_data_holder.terminations)\n",
"print(interface_data_holder.get_interfaces_for_termination(0))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. Plot the results\n",
"## 5. Plot the results\n",
"\n",
"Plot the number of atoms vs strain. Adjust the parameters as needed.\n"
]
Expand All @@ -322,89 +224,24 @@
"metadata": {},
"outputs": [],
"source": [
"import plotly.graph_objs as go\n",
"from collections import defaultdict\n",
"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(interface_data_holder, PLOT_SETTINGS)\n",
"\n",
"def plot_strain_vs_atoms(sorted_interfaces, terminations, settings):\n",
" # Create a mapping from termination to its index\n",
" termination_to_index = {termination: i for i, termination in enumerate(terminations)}\n",
"\n",
" grouped_interfaces = defaultdict(list)\n",
" for termination, interfaces in sorted_interfaces.items():\n",
" for index, interface_data in enumerate(interfaces):\n",
" strain_percentage = interface_data[\"mean_abs_strain\"] * 100\n",
" num_sites = interface_data[\"interface\"].num_sites\n",
" key = (strain_percentage, num_sites)\n",
" grouped_interfaces[key].append((index, termination))\n",
"\n",
" data = []\n",
" for (strain, num_sites), indices_and_terminations in grouped_interfaces.items():\n",
" termination_indices = defaultdict(list)\n",
" for index, termination in indices_and_terminations:\n",
" termination_indices[termination].append(index)\n",
" all_indices = [index for indices in termination_indices.values() for index in indices]\n",
" index_range = f\"{min(all_indices)}-{max(all_indices)}\" if len(all_indices) > 1 else str(min(all_indices))\n",
"\n",
" hover_text = \"<br>-----<br>\".join(\n",
" f\"Termination: {termination}<br>Termination index: {termination_to_index[termination]}<br>Interfaces Index Range: {index_range}<br>Strain: {strain:.2f}%<br>Atoms: {num_sites}\"\n",
" for termination, indices in termination_indices.items()\n",
" )\n",
" trace = go.Scatter(\n",
" x=[strain],\n",
" y=[num_sites],\n",
" text=[hover_text],\n",
" mode=\"markers\",\n",
" hoverinfo=\"text\",\n",
" name=f\"Indices: {index_range}\",\n",
" )\n",
" data.append(trace)\n",
"\n",
" layout = go.Layout(\n",
" xaxis=dict(title=\"Strain (%)\", type=settings[\"X_SCALE\"]),\n",
" yaxis=dict(title=\"Number of atoms\", type=settings[\"Y_SCALE\"]),\n",
" hovermode=\"closest\",\n",
" height=settings[\"HEIGHT\"],\n",
" legend_title_text=\"Interfaces Index Range\",\n",
" )\n",
" fig = go.Figure(data=data, layout=layout)\n",
" fig.show()\n",
"\n",
"\n",
"plot_strain_vs_atoms(sorted_interfaces, terminations, PLOT_SETTINGS)\n",
"\n",
"for i, termination in enumerate(terminations):\n",
" print(f\"Termination {i}:\", termination)"
"print(interface_data_holder.terminations)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. Select the interface with the desired termination and strain\n",
"\n",
"The data in `sorted_interfaces` now contains an object with the following structure:\n",
"\n",
"```json\n",
"{\n",
" \"('C_P6/mmm_2', 'Si_R-3m_1')\": [\n",
" { ...interface for ('C_P6/mmm_2', 'Si_R-3m_1') at index 0...},\n",
" { ...interface for ('C_P6/mmm_2', 'Si_R-3m_1') at index 1...},\n",
" ...\n",
" ],\n",
" \"<termination at index 1>\": [\n",
" { ...interface for 'termination at index 1' at index 0...},\n",
" { ...interface for 'termination at index 1' at index 1...},\n",
" ...\n",
" ]\n",
"}\n",
"```\n",
"## 6. Select the interface with the desired termination and strain\n",
"\n",
"Select the index for termination first, and for it - the index in the list of corresponding interfaces sorted by strain (index 0 has minimum strain).\n"
]
Expand All @@ -416,22 +253,20 @@
"outputs": [],
"source": [
"termination_index = 0\n",
"interface_index = 0\n",
"\n",
"termination = terminations[termination_index]\n",
"\n",
"interface = sorted_interfaces[termination][interface_index][\"interface\"]\n",
"interfaces_sorted_by_strain_and_size = interface_data_holder.get_interfaces_for_termination(termination_index)\n",
"\n",
"interface_strain = f\"{sorted_interfaces[termination][interface_index]['mean_abs_strain'] * 100:.2f}%\""
"interfaces_range = slice(0, 1) # select the first interface with the lowest strain\n",
"selected_interface = interfaces_sorted_by_strain_and_size[interfaces_range]\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 8. Apply relaxation to the interface\n",
"## 7. Apply relaxation to the interface\n",
"\n",
"### 8.1. Apply relaxation to the selected interface with ASE\n",
"### 7.1. Apply relaxation to the selected interface with ASE\n",
"\n",
"Optimizer is set from the available options in the settings and EMT is used as the energy calculator."
]
Expand Down Expand Up @@ -524,7 +359,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### 8.2. View structure before and after relaxation\n"
"### 7.2. View structure before and after relaxation\n"
]
},
{
Expand Down Expand Up @@ -587,7 +422,7 @@
"collapsed": false
},
"source": [
"### 8.3. Calculate the energy metrics\n",
"### 7.3. Calculate the energy metrics\n",
"Calculate the energy metrics for the relaxed interface.\n",
"The effective delta energy per area calculation accounts for the energy contribution of each component (substrate and layer) relative to their proportion in the overall interface. \n"
]
Expand Down Expand Up @@ -683,7 +518,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## 9. Pass relaxed interface to Materials Designer"
"## 8. Pass relaxed interface to Materials Designer"
]
},
{
Expand All @@ -700,9 +535,20 @@
" 'name'] = f\"{esse_final_interface['name']}, Interface, Strain: {interface_strain}, {name_relaxation_suffix}\"\n",
"\n",
"materials_out = [esse_final_interface]\n",
"set_data(\"materials\", materials_out)"
"# set_data(\"materials\", materials_out)"
]
},
{
"cell_type": "code",
"outputs": [],
"source": [
"!pip list"
],
"metadata": {
"collapsed": false
},
"execution_count": null
},
{
"cell_type": "markdown",
"metadata": {
Expand Down