From 9c38d708742719e96e38fa3cc0c772fd32b353af Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Sun, 9 Feb 2025 16:33:12 -0800 Subject: [PATCH 1/2] feat: add heart shape cutout --- .../create_cutout_heart_shape.ipynb | 313 ++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100644 other/materials_designer/create_cutout_heart_shape.ipynb diff --git a/other/materials_designer/create_cutout_heart_shape.ipynb b/other/materials_designer/create_cutout_heart_shape.ipynb new file mode 100644 index 00000000..12816085 --- /dev/null +++ b/other/materials_designer/create_cutout_heart_shape.ipynb @@ -0,0 +1,313 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Create a custom-shape cutout\n", + "\n", + "Create a slab with a complex cutout pattern.\n", + "By default, this notebook generates a structure of etching pattern:\n", + "- Two vertical side walls\n", + "- Two parallel channels at the top\n", + "- A deeper central cavity\n", + "\n", + "

Usage

\n", + "\n", + "1. Make sure to select Input Material (in the outer runtime) before running the notebook.\n", + "2. Set structural parameters in cell 1.2 below\n", + "4. Click \"Run\" > \"Run All\" to create the structure\n", + "5. Scroll down to view the resulting structure from multiple angles\n", + "\n", + "## Resulting structure:\n", + "" + ], + "metadata": { + "collapsed": false + }, + "id": "f2e1e795020d7b3f" + }, + { + "cell_type": "markdown", + "source": [ + "## 1. Prepare the Environment\n", + "### 1.1. 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 + }, + "id": "98aa134f51746218" + }, + { + "cell_type": "code", + "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(\"\")" + ], + "metadata": { + "collapsed": false + }, + "id": "280f9794a876678b", + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "### 1.2. Set up structure parameters", + "id": "b3d4d3ea7b589f89" + }, + { + "metadata": { + "collapsed": false + }, + "cell_type": "code", + "source": [ + "# Slab parameters\n", + "MILLER_INDICES = (0, 0, 1)\n", + "THICKNESS = 10 # unit cell layers\n", + "VACUUM = 6.0 # Angstrom\n", + "XY_SUPERCELL_MATRIX = [[10, 0], [0, 10]]\n", + "\n", + "# Heart shape parameters in crystal units\n", + "HEART_WIDTH = 0.75 # Width of heart relative to cell\n", + "HEART_HEIGHT = 0.8 # Height of heart relative to cell\n", + "NAME = \"Diamond Heart Y-taper - C\"" + ], + "id": "5177e239254e3601", + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 1.3. Create a condition on coordinates\n" + ], + "metadata": { + "collapsed": false + }, + "id": "361c291aaf3feb2a" + }, + { + "cell_type": "code", + "source": [ + "\n", + "\n", + "from typing import List\n", + "from mat3ra.made.tools.utils.coordinate import CoordinateCondition\n", + "\n", + "class YTaperedHeartShapeCondition(CoordinateCondition):\n", + " \"\"\"\n", + " Defines a heart-shaped structure with y-direction tapering applied.\n", + " All dimensions are specified as fractions of the total size (0.0 to 1.0).\n", + " \"\"\"\n", + " width: float = 0.75 # Heart width relative to cell size\n", + " height: float = 0.8 # Heart height relative to cell size\n", + " max_thickness: float = 0.4 # Maximum thickness (y-direction) at the top\n", + "\n", + " def condition(self, coordinate: List[float]) -> bool:\n", + " \"\"\"\n", + " Returns True for positions that should be removed.\n", + " Creates a heart shape with y-direction tapering.\n", + " \"\"\"\n", + " x, y, z = coordinate\n", + "\n", + " # Center and scale coordinates\n", + " x = (x - 0.5) * 2 / self.width\n", + " y = (y - 0.5) * 2 / self.width\n", + " z = (z - 0.5) * 2 / self.height\n", + "\n", + " # Heart shape equation (in xz-plane)\n", + " heart_equation = (x**2 + z**2 - 1)**3 - x**2 * z**3\n", + " in_heart = heart_equation <= 0 # True if within heart shape\n", + "\n", + " # Apply tapering: dynamically reduce thickness in the y-direction\n", + " taper_factor = 1 - max(0, -z * 0.7) # Adjust tapering intensity\n", + " dynamic_thickness = self.max_thickness * taper_factor\n", + "\n", + " in_thickness = abs(y) <= dynamic_thickness # Adjust thickness dynamically\n", + "\n", + " # Return True to remove atoms OUTSIDE the heart shape\n", + " return not (in_heart and in_thickness)\n", + "\n", + "# Create the condition\n", + "condition = YTaperedHeartShapeCondition(\n", + " width=HEART_WIDTH,\n", + " height=HEART_HEIGHT,\n", + " max_thickness=0.4 # Adjustable max thickness\n", + ").condition\n" + ], + "metadata": { + "collapsed": false + }, + "id": "56c8227695643174", + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 1.3. Get input materials" + ], + "metadata": { + "collapsed": false + }, + "id": "91724db55eddad60" + }, + { + "cell_type": "code", + "source": [ + "from utils.jupyterlite import get_materials\n", + "\n", + "materials = get_materials(globals())\n", + "material = materials[0]" + ], + "metadata": { + "collapsed": false + }, + "id": "ceebf2a5229da67c", + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "### 1.4. Preview the material" + ], + "metadata": { + "collapsed": false + }, + "id": "13964644436b4156" + }, + { + "cell_type": "code", + "source": [ + "from utils.visualize import visualize_materials as visualize\n", + "\n", + "visualize(material, repetitions=[1, 1, 1], rotation=\"0x\")\n", + "visualize(material, repetitions=[1, 1, 1], rotation=\"-90x\")" + ], + "metadata": { + "collapsed": false + }, + "id": "45f0c424ece00186", + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "## 2. Create target material\n", + "### 2.1. Create a slab and apply the cutout condition" + ], + "metadata": { + "collapsed": false + }, + "id": "615800437b2ef7a" + }, + { + "cell_type": "code", + "source": [ + "from mat3ra.made.tools.modify import filter_by_condition_on_coordinates, add_vacuum\n", + "from mat3ra.made.tools.build.slab import create_slab, SlabConfiguration\n", + "\n", + "slab_config = SlabConfiguration(\n", + " bulk=material,\n", + " miller_indices=MILLER_INDICES,\n", + " thickness=THICKNESS,\n", + " vacuum=0,\n", + " xy_supercell_matrix=XY_SUPERCELL_MATRIX,\n", + " use_orthogonal_z=True,\n", + " use_conventional_cell=True,\n", + ")\n", + "\n", + "slab_unit_cell = create_slab(slab_config)\n", + "resulting_material = filter_by_condition_on_coordinates(slab_unit_cell, condition)\n", + "resulting_material = add_vacuum(resulting_material, VACUUM)" + ], + "metadata": { + "collapsed": false + }, + "id": "422815d29aa347a1", + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "## 3. Visualize the result" + ], + "metadata": { + "collapsed": false + }, + "id": "57cc38ec0df3c1f7" + }, + { + "cell_type": "code", + "source": [ + "visualize(resulting_material, repetitions=[1, 1, 1], rotation=\"0x\")\n", + "visualize(resulting_material, repetitions=[1, 1, 1], rotation=\"-90x\")\n", + "visualize(resulting_material, repetitions=[1, 1, 1], rotation=\"-90x,-90y\")" + ], + "metadata": { + "collapsed": false + }, + "id": "2a9627cd4a261067", + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "source": [ + "# 4. Pass material to the outside runtime" + ], + "metadata": { + "collapsed": false + }, + "id": "c67e6f5363e80942" + }, + { + "cell_type": "code", + "source": [ + "from utils.jupyterlite import set_materials\n", + "\n", + "resulting_material.name = NAME\n", + "set_materials(resulting_material)" + ], + "metadata": { + "collapsed": false + }, + "id": "cbee60d4b936e5cb", + "outputs": [], + "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 +} From 2863c7ce450fbac095d4f80f59a778fa1462f492 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Sun, 9 Feb 2025 16:33:47 -0800 Subject: [PATCH 2/2] chore: rename --- other/materials_designer/create_cutout_heart_shape.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/other/materials_designer/create_cutout_heart_shape.ipynb b/other/materials_designer/create_cutout_heart_shape.ipynb index 12816085..6ac3ea47 100644 --- a/other/materials_designer/create_cutout_heart_shape.ipynb +++ b/other/materials_designer/create_cutout_heart_shape.ipynb @@ -3,7 +3,7 @@ { "cell_type": "markdown", "source": [ - "# Create a custom-shape cutout\n", + "# Create a heart-shape cutout\n", "\n", "Create a slab with a complex cutout pattern.\n", "By default, this notebook generates a structure of etching pattern:\n", @@ -229,7 +229,7 @@ ")\n", "\n", "slab_unit_cell = create_slab(slab_config)\n", - "resulting_material = filter_by_condition_on_coordinates(slab_unit_cell, condition)\n", + "resulting_material = filter_by_condition_on_coordinates(slab_unit_cell, condition, invert_selection=True)\n", "resulting_material = add_vacuum(resulting_material, VACUUM)" ], "metadata": {