|
48 | 48 | }, |
49 | 49 | { |
50 | 50 | "cell_type": "code", |
51 | | - "outputs": [], |
52 | 51 | "source": [ |
53 | 52 | "import sys\n", |
54 | 53 | "\n", |
|
58 | 57 | " await micropip.install('mat3ra-api-examples', deps=False)\n", |
59 | 58 | " from utils.jupyterlite import install_packages\n", |
60 | 59 | "\n", |
61 | | - " await install_packages(\"create_cluster_custom_shape.ipynb\")" |
| 60 | + " await install_packages(\"\")" |
62 | 61 | ], |
63 | 62 | "metadata": { |
64 | 63 | "collapsed": false |
65 | 64 | }, |
66 | 65 | "id": "d9e6be14343d00a1", |
| 66 | + "outputs": [], |
67 | 67 | "execution_count": null |
68 | 68 | }, |
69 | 69 | { |
|
78 | 78 | }, |
79 | 79 | { |
80 | 80 | "cell_type": "code", |
81 | | - "outputs": [], |
82 | 81 | "source": [ |
83 | 82 | "RADIUS = 0.3 # in crystal units\n", |
84 | 83 | "VACUUM = 10.0 # in Angstroms on each side\n", |
|
90 | 89 | "collapsed": false |
91 | 90 | }, |
92 | 91 | "id": "9d8b1890b34d850a", |
| 92 | + "outputs": [], |
93 | 93 | "execution_count": null |
94 | 94 | }, |
95 | 95 | { |
|
104 | 104 | }, |
105 | 105 | { |
106 | 106 | "cell_type": "code", |
107 | | - "outputs": [], |
108 | 107 | "source": [ |
109 | 108 | "import numpy as np\n", |
| 109 | + "from scipy.spatial import ConvexHull\n", |
110 | 110 | "from typing import List\n", |
111 | | - "from icosphere import icosphere\n", |
112 | 111 | "from mat3ra.made.tools.utils.coordinate import CoordinateCondition\n", |
113 | 112 | "\n", |
114 | 113 | "\n", |
115 | | - "# Example of a custom coordinate condition (icosahedron). Adapt coordinate conditions to your needs.\n", |
116 | 114 | "class CustomCoordinateCondition(CoordinateCondition):\n", |
117 | | - " \"\"\"Creates an icosahedron shape using the icosphere module\"\"\"\n", |
| 115 | + " \"\"\"Creates a regular polyhedron shape using SciPy's ConvexHull\"\"\"\n", |
118 | 116 | " radius: float = 1\n", |
119 | | - " frequency: int = 1\n", |
120 | | - " vertices: List[List[float]] = icosphere(1)[0]\n", |
121 | | - " faces: List[List[int]] = icosphere(1)[1]\n", |
122 | 117 | " center: List[float] = [0.5, 0.5, 0.5]\n", |
123 | 118 | "\n", |
| 119 | + " @property\n", |
| 120 | + " def _hull_planes(self):\n", |
| 121 | + " t = (1 + np.sqrt(5)) / 2\n", |
| 122 | + " vertices = np.array([\n", |
| 123 | + " [-1, t, 0], [1, t, 0], [-1, -t, 0], [1, -t, 0],\n", |
| 124 | + " [0, -1, t], [0, 1, t], [0, -1, -t], [0, 1, -t],\n", |
| 125 | + " [t, 0, -1], [t, 0, 1], [-t, 0, -1], [-t, 0, 1]\n", |
| 126 | + " ]) * self.radius / np.sqrt(1 + t*t)\n", |
| 127 | + " return ConvexHull(vertices).equations\n", |
| 128 | + "\n", |
124 | 129 | " def condition(self, coordinate: List[float]) -> bool:\n", |
125 | | - " \"\"\"Returns True if point is inside icosahedron\"\"\"\n", |
126 | | - " coordinate = np.array(coordinate) - self.center\n", |
127 | | - " for face in self.faces:\n", |
128 | | - " a, b, c = face\n", |
129 | | - " normal = np.cross(self.vertices[b] - self.vertices[a], self.vertices[c] - self.vertices[a])\n", |
130 | | - " normal = normal / np.linalg.norm(normal)\n", |
131 | | - " if np.dot(normal, coordinate) > self.radius:\n", |
132 | | - " return False\n", |
133 | | - " return True\n", |
134 | | - " \n", |
| 130 | + " \"\"\"Returns True if point is inside the polyhedron\"\"\"\n", |
| 131 | + " point = np.array(coordinate) - self.center\n", |
| 132 | + " return all(np.dot(plane[:3], point) + plane[3] <= 0\n", |
| 133 | + " for plane in self._hull_planes)\n", |
| 134 | + "\n", |
135 | 135 | " \n", |
136 | 136 | "condition = CustomCoordinateCondition(radius=RADIUS).condition" |
137 | 137 | ], |
138 | 138 | "metadata": { |
139 | 139 | "collapsed": false |
140 | 140 | }, |
141 | 141 | "id": "8e382d5ab459e2d", |
| 142 | + "outputs": [], |
142 | 143 | "execution_count": null |
143 | 144 | }, |
144 | 145 | { |
|
153 | 154 | }, |
154 | 155 | { |
155 | 156 | "cell_type": "code", |
156 | | - "outputs": [], |
157 | 157 | "source": [ |
158 | 158 | "from utils.jupyterlite import get_materials\n", |
159 | 159 | "\n", |
|
163 | 163 | "collapsed": false |
164 | 164 | }, |
165 | 165 | "id": "be38fdda1984c654", |
| 166 | + "outputs": [], |
166 | 167 | "execution_count": null |
167 | 168 | }, |
168 | 169 | { |
|
178 | 179 | }, |
179 | 180 | { |
180 | 181 | "cell_type": "code", |
181 | | - "outputs": [], |
182 | 182 | "source": [ |
183 | | - "from mat3ra.made.tools.build.nanoparticle import ASEBasedNanoparticleConfiguration\n", |
184 | | - "from mat3ra.made.tools.build.nanoparticle.enums import ASENanoparticleShapesEnum\n", |
185 | | - "\n", |
| 183 | + "from mat3ra.made.tools.build.nanoparticle import SlabBasedNanoparticleConfiguration\n", |
186 | 184 | "\n", |
187 | | - "config = ASEBasedNanoparticleConfiguration(\n", |
| 185 | + "config = SlabBasedNanoparticleConfiguration(\n", |
188 | 186 | " material=materials[0],\n", |
| 187 | + " condition_builder=condition,\n", |
189 | 188 | " supercell_size=SUPERCELL_SIZE,\n", |
190 | | - " vacuum=VACUUM,\n", |
191 | | - " z_orientation=Z_ORIENTATION,\n", |
192 | | - " coordinate_condition=condition\n", |
193 | | - ")\n" |
| 189 | + ")" |
194 | 190 | ], |
195 | 191 | "metadata": { |
196 | 192 | "collapsed": false |
197 | 193 | }, |
198 | | - "id": "8fbe260fa14db47a" |
| 194 | + "id": "8fbe260fa14db47a", |
| 195 | + "outputs": [], |
| 196 | + "execution_count": null |
199 | 197 | }, |
200 | 198 | { |
201 | 199 | "cell_type": "markdown", |
|
209 | 207 | }, |
210 | 208 | { |
211 | 209 | "cell_type": "code", |
212 | | - "outputs": [], |
213 | 210 | "source": [ |
214 | | - "from mat3ra.made.tools.build.nanoparticle import ASEBasedNanoparticleBuilder" |
| 211 | + "from mat3ra.made.tools.build.nanoparticle import create_nanoparticle\n", |
| 212 | + "\n", |
| 213 | + "cluster = create_nanoparticle(config)" |
215 | 214 | ], |
216 | 215 | "metadata": { |
217 | 216 | "collapsed": false |
218 | 217 | }, |
219 | 218 | "id": "a990fa35742d7269", |
| 219 | + "outputs": [], |
220 | 220 | "execution_count": null |
221 | 221 | }, |
222 | 222 | { |
|
231 | 231 | }, |
232 | 232 | { |
233 | 233 | "cell_type": "code", |
234 | | - "outputs": [], |
235 | 234 | "source": [ |
236 | 235 | "from mat3ra.made.lattice import Lattice\n", |
237 | 236 | "\n", |
|
245 | 244 | "collapsed": false |
246 | 245 | }, |
247 | 246 | "id": "4f78c4743b370c3b", |
| 247 | + "outputs": [], |
248 | 248 | "execution_count": null |
249 | 249 | }, |
250 | 250 | { |
|
259 | 259 | }, |
260 | 260 | { |
261 | 261 | "cell_type": "code", |
262 | | - "outputs": [], |
263 | 262 | "source": [ |
264 | | - "visualize([{\"material\": slab, \"title\": \"Original material\"},\n", |
265 | | - " {\"material\": cluster, \"title\": f\"Cluster\"}])\n", |
266 | | - "\n", |
267 | | - "visualize([{\"material\": slab, \"title\": \"Original material\"},\n", |
268 | | - " {\"material\": cluster, \"title\": f\"Cluster\"}], rotation=\"-90x\")" |
| 263 | + "from utils.visualize import visualize_materials as visualize\n", |
| 264 | + "visualize([{\"material\": cluster, \"title\": f\"Cluster\"},\n", |
| 265 | + " {\"material\": cluster, \"title\": f\"Cluster\", \"rotation\": \"-90x\"}])" |
269 | 266 | ], |
270 | 267 | "metadata": { |
271 | 268 | "collapsed": false |
272 | 269 | }, |
273 | 270 | "id": "509b18661a069e42", |
| 271 | + "outputs": [], |
274 | 272 | "execution_count": null |
275 | 273 | }, |
276 | 274 | { |
|
285 | 283 | }, |
286 | 284 | { |
287 | 285 | "cell_type": "code", |
288 | | - "outputs": [], |
289 | 286 | "source": [ |
290 | 287 | "from utils.jupyterlite import set_materials\n", |
291 | 288 | "\n", |
|
296 | 293 | "collapsed": false |
297 | 294 | }, |
298 | 295 | "id": "61daa5afcbc078a9", |
| 296 | + "outputs": [], |
299 | 297 | "execution_count": null |
300 | 298 | } |
301 | 299 | ], |
|
0 commit comments