crystalbuilder 0.5.4__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of crystalbuilder might be problematic. Click here for more details.

@@ -0,0 +1,379 @@
1
+ import numpy as np
2
+ from crystalbuilder.conversions.t3d import geo_to_tidy3d
3
+ from crystalbuilder import lattice as lat
4
+ from crystalbuilder import geometry as geo
5
+ from crystalbuilder.conversions import lumc as lc
6
+ import platform
7
+ if platform.system() == 'Windows':
8
+ pass
9
+ else:
10
+ import meep as mp
11
+
12
+ try:
13
+ import lumpy.simobjects as so
14
+ except ModuleNotFoundError:
15
+ pass
16
+ debug = "off"
17
+
18
+ def vectorize(list):
19
+ """Converts list of x,y,z coordinates to mp.Vector3 object
20
+
21
+ This simply assigns the first 3 indices to 'x','y','z' and returns the mp.Vector3('x','y','z').
22
+ Thus it will also work for any index-able data format (e.g. numpy arrays and existing mp.Vector3 objects)
23
+
24
+ Parameters
25
+ ----------
26
+ list : ArrayLike
27
+ an ArrayLike object of length 3 (anything beyond will be ignored)
28
+
29
+ Returns
30
+ -------
31
+ mp.Vector3()
32
+ mp.Vector3 object mp.Vector3(x,y,z)
33
+
34
+ """
35
+ x = list[0]
36
+ y = list[1]
37
+ z = list[2]
38
+ return mp.Vector3(x,y,z)
39
+
40
+ def unpack_supercell(supercell):
41
+ """Turns supercell into a list of geometry objects
42
+
43
+ Parameters
44
+ ----------
45
+ supercell : gm.SuperCell()
46
+ A SuperCell object from geometry.py
47
+
48
+ Returns
49
+ -------
50
+ [structures]: list
51
+ list of the geometry objects in SuperCell
52
+
53
+ """
54
+
55
+ structures = supercell.structures
56
+ return structures
57
+
58
+ def flatten(list):
59
+ """ Some of these methods can accidentally create nested lists, so this function can be used in try statements to correct those """
60
+ try:
61
+ if isinstance(list, list):
62
+ flat_list = [item for sublist in list for item in sublist]
63
+ except:
64
+ flat_list = list
65
+ return flat_list
66
+
67
+ def _geo_to_meep(geometry_object, material, ismpb = False, **kwargs):
68
+ """ Lower-level function to convert Geometries into MEEP objects. It's recommended to call the geo_to_meep function instead.
69
+
70
+ Parameters
71
+ -----------
72
+ geometry_object : list or Geometry
73
+ an object or list of objects from geometry.py
74
+
75
+ material : mp.Material()
76
+ MEEP material for the converted object
77
+
78
+ ismpb : bool
79
+ MPB is a MEEP submodule that works for photonic crystals. The coordinate space is different than conventional MEEP. This arg determines if the resulting objects will use MPB coordinates or the MEEP ones (default)
80
+
81
+ **kwargs : string
82
+ lattice: mpb.lattice()
83
+ lattice for building MPB geometry, only necessary if mpb_mode is True. This is handled automatically by the higher level geo_to_mpb function
84
+
85
+
86
+ Returns
87
+ -------
88
+ [geom_list] : list
89
+ list of MEEP objects
90
+
91
+ """
92
+
93
+ mpb_mode = ismpb
94
+ #print("MPB Mode is ", str(mpb_mode))
95
+ geom_list = []
96
+ if mpb_mode == True:
97
+ geo_lattice = kwargs.get("lattice", None)
98
+
99
+
100
+ try:
101
+ for m in geometry_object:
102
+ if isinstance(m, geo.SuperCell):
103
+ if debug=="on": print("This is running the iterable Supercell")
104
+ if ismpb == True:
105
+ innerlist = _geo_to_meep(m, material, ismpb=mpb_mode, lattice=geo_lattice)
106
+ geom_list.append(innerlist)
107
+ else:
108
+ innerlist = _geo_to_meep(m, material, ismpb=mpb_mode)
109
+ geom_list.append(innerlist)
110
+
111
+ elif isinstance(m, geo.Cylinder):
112
+ if debug=="on": print("This is running the iterable cylinder")
113
+
114
+ if ismpb == True:
115
+ k = vectorize(m.center)
116
+ newcent = mp.cartesian_to_lattice(k, geo_lattice)
117
+ else:
118
+ newcent = vectorize(m.center)
119
+
120
+ item = mp.Cylinder(radius=m.radius, axis= m.axis, height=m.height, center=newcent, material=material)
121
+ geom_list.append(item)
122
+
123
+ elif isinstance(m, geo.Triangle):
124
+ if debug=="on": print("This is running the iterable triangle")
125
+
126
+ newverts = []
127
+ for k in m.vertlist:
128
+ k = vectorize(k)
129
+ if mpb_mode == True:
130
+ newverts.append(mp.cartesian_to_lattice(k, geo_lattice))
131
+ elif mpb_mode == False:
132
+ newverts.append(k)
133
+
134
+ item = mp.Prism(vertices = newverts, axis = vectorize(m.axis), height = m.height, material=material)
135
+ geom_list.append(item)
136
+
137
+ elif isinstance(m, geo.Sphere):
138
+ if ismpb == True:
139
+ k = vectorize(m.center)
140
+ newcent = mp.cartesian_to_lattice(k, geo_lattice)
141
+ else:
142
+ newcent = vectorize(m.center)
143
+
144
+ item = mp.Sphere(radius=m.radius,center=newcent, material=material)
145
+ geom_list.append(item)
146
+
147
+
148
+
149
+
150
+ except TypeError:
151
+ if isinstance(geometry_object, geo.SuperCell):
152
+ if debug=="on": print("This is running the single Supercell")
153
+ structs = unpack_supercell(geometry_object)
154
+ m = structs
155
+ newlist = _geo_to_meep(m, material)
156
+ geom_list.append(newlist)
157
+
158
+ elif isinstance(geometry_object, geo.Cylinder):
159
+ m = geometry_object
160
+ if debug=="on": print("This is running the single cylinder")
161
+ if ismpb == True:
162
+ k = vectorize(m.center)
163
+ newcent = mp.cartesian_to_lattice(k, geo_lattice)
164
+ else:
165
+ newcent = vectorize(m.center)
166
+ geom_list.append(mp.Cylinder(radius=m.radius, axis= m.axis, height=m.height, center=newcent, material=material))
167
+
168
+ elif isinstance(geometry_object, geo.Triangle):
169
+ if debug=="on": print("This is running the single triangle")
170
+ m = geometry_object
171
+ if ismpb == True:
172
+ newverts = []
173
+ for k in m.verttuple:
174
+ k = vectorize(k)
175
+ newverts.append(mp.cartesian_to_lattice(k, geo_lattice))
176
+ else:
177
+ newverts = vectorize(m.verttuple)
178
+ geom_list.append(mp.Prism(vertices = newverts, axis = vectorize(m.axis), height = m.height, material=material))
179
+
180
+ elif isinstance(geometry_object, geo.Sphere):
181
+ m = geometry_object
182
+ if ismpb == True:
183
+ k = vectorize(m.center)
184
+ newcent = mp.cartesian_to_lattice(k, geo_lattice)
185
+ else:
186
+ newcent = vectorize(m.center)
187
+
188
+ item = mp.Cylinder(radius=m.radius, center=newcent, material=material)
189
+ geom_list.append(item)
190
+
191
+
192
+
193
+ return geom_list
194
+
195
+ def geo_to_meep(geometry_object, material):
196
+ """Converts CrystalBuilder geometry object(s) to the corresponding MEEP object(s) with defined material.
197
+
198
+ This is a higher level wrapper of the _geo_to_meep function, which I have yet to document.
199
+ This simplifies the calling, as it only takes two arguments.
200
+
201
+ Parameters
202
+ ----------
203
+ geometry_object : list or Geometry
204
+ an object or list of objects geometry.py
205
+
206
+ material : mp.Material()
207
+ MEEP material
208
+
209
+ Returns
210
+ -------
211
+ [meep_list]: list
212
+ list of MEEP objects
213
+
214
+ """
215
+ geom_list = _geo_to_meep(geometry_object, material)
216
+ newlist = flatten(geom_list)
217
+ meep_list = flatten(newlist)
218
+ return meep_list
219
+
220
+ def geo_to_mpb(geometry_object, material, lattice):
221
+ """Converts CrystalBuilder geometry object(s) to the corresponding MPB object(s) with defined material.
222
+
223
+ This is a higher level wrapper of the _geo_to_meep function, which I have yet to document.
224
+ MPB defines geometry on an arbitrary basis determined by the simulation's lattice. This requires an extra parameter, 'lattice'.
225
+
226
+ Parameters
227
+ ----------
228
+ geometry_object : Geometry or list of Geometry
229
+ an object or list of objects
230
+ material : mp.Material()
231
+ MPB material
232
+ lattice : mpb.lattice()
233
+ lattice for MPB simulation, usually assigned to geometry_lattice
234
+
235
+
236
+ Returns
237
+ -------
238
+ [mpb_list]: list
239
+ list of mpb objects
240
+
241
+ """
242
+
243
+
244
+ geom_list = _geo_to_meep(geometry_object, material, ismpb=True, lattice=lattice)
245
+ newlist = flatten(geom_list)
246
+ mpb_list = flatten(newlist)
247
+ return mpb_list
248
+
249
+ def _geo_to_lumerical(geometry_object, material):
250
+ """
251
+ Converts Geometry object to list of lumerical objects
252
+
253
+ ## IN PROGRESS ##
254
+
255
+ """
256
+
257
+ #get index from meep material, but treat it as a dielectric constant otherwise
258
+ try:
259
+ if isinstance(material, mp.Medium):
260
+ index = np.sqrt(material.epsilon_diag[0])
261
+ else:
262
+ index = material
263
+ except NameError:
264
+ index = material
265
+
266
+ geom_list = []
267
+ try:
268
+ for m in geometry_object:
269
+ if isinstance(m, geo.SuperCell):
270
+ if debug=="on": print("This is running the iterable Supercell")
271
+ innerlist = _geo_to_lumerical(m, material)
272
+ geom_list.append(innerlist)
273
+
274
+ elif isinstance(m, geo.Cylinder):
275
+ if debug=="on": print("This is running the iterable cylinder")
276
+ lmgeom = lc.convert_cylinder(m, material='dielectric', index=index)
277
+ geom_list.append(lmgeom)
278
+
279
+ elif isinstance(m, geo.Triangle):
280
+ if debug=="on": print("This is running the iterable Triangle")
281
+ lmgeom = lc.convert_prism(m, material='dielectric', index=index)
282
+ geom_list.append(lmgeom)
283
+
284
+ except TypeError:
285
+ if isinstance(geometry_object, geo.SuperCell):
286
+ if debug=="on": print("This is running the single Supercell")
287
+ structs = unpack_supercell(geometry_object)
288
+ m = structs
289
+ newlist = _geo_to_lumerical(m, material)
290
+ geom_list.append(newlist)
291
+
292
+ elif isinstance(geometry_object, geo.Cylinder):
293
+ m = geometry_object
294
+ if debug=="on": print("This is creating a single cylinder named")
295
+ lmgeom = lmgeom = lc.convert_cylinder(m, material='dielectric', index=index)
296
+ geom_list.append(lmgeom)
297
+
298
+ elif isinstance(geometry_object, geo.Triangle):
299
+ m = geometry_object
300
+ if debug=="on": print("This is running the single Triangle")
301
+ lmgeom = lc.convert_prism(m, material='dielectric', index=index)
302
+ geom_list.append(lmgeom)
303
+
304
+
305
+
306
+ return geom_list
307
+
308
+ def to_geo_lattice(mpblattice):
309
+ """converts mpb's `Lattice` to the CrystalBuilder Lattice
310
+
311
+ Parameters
312
+ ----------
313
+ mpblattice : mp.Lattice()
314
+ mpb/MEEP lattice object
315
+
316
+
317
+ Returns
318
+ -------
319
+ lat.Lattice()
320
+ CrystalBuilder lattice object
321
+
322
+
323
+ """
324
+
325
+ if isinstance(mpblattice, mp.Lattice):
326
+ magnitude = np.asarray(mpblattice.size)
327
+ basis1 = np.asarray(mpblattice.basis1)
328
+ basis2 = np.asarray(mpblattice.basis2)
329
+ basis3 = np.asarray(mpblattice.basis3)
330
+ lattice = lat.Lattice(a1=basis1, a2=basis2, a3=basis3, magnitude=magnitude)
331
+ return lattice
332
+ else:
333
+ print("Error: Please pass a MEEP lattice object as the argument")
334
+
335
+ def to_mpb_lattice(geolattice):
336
+ """converts crystalbuilder Lattice to the mpb lattice
337
+
338
+ Parameters
339
+ ----------
340
+ lat.Lattice()
341
+ CrystalBuilder lattice object
342
+
343
+
344
+ Returns
345
+ -------
346
+ mpblattice : mp.Lattice()
347
+ mpb/MEEP lattice object
348
+ """
349
+
350
+ if isinstance(geolattice, lat.Lattice):
351
+ magnitude = np.asarray(geolattice.magnitude)
352
+ basis1 = np.asarray(geolattice.a1)
353
+ basis2 = np.asarray(geolattice.a2)
354
+ basis3 = np.asarray(geolattice.a3)
355
+ lattice = mp.Lattice(size = magnitude, basis1 = basis1, basis2 = basis2, basis3=basis3)
356
+ return lattice
357
+ else:
358
+ print("Error: Please pass a crystalbuilder lattice object as the argument")
359
+
360
+ if __name__ == '__main__':
361
+ """testing code"""
362
+
363
+ # mat1 = mp.Medium(epsilon=4)
364
+ # geometry_lattice = mp.Lattice(size=mp.Vector3(1, 1),
365
+ # basis1=mp.Vector3(np.sqrt(3) / 2, 0.5),
366
+ # basis2=mp.Vector3(0,0.5))
367
+
368
+ # tri = geo.eqTriangle(1, .5)
369
+ # print(tri.vertices.shape)
370
+ # print(type(tri))
371
+
372
+ # newgeo = _geo_to_lumerical(tri, mat1)
373
+
374
+ # print(newgeo[0].out())
375
+
376
+
377
+ cylinder = geo.Cylinder.from_vertices([[0,0,0], [1,1,1]], radius=.2)
378
+ cylinder2 = geo.Cylinder(center=[1,1,0], radius=.1, height=3, axis=2)
379
+ newgeo = geo_to_tidy3d([cylinder, cylinder2], material=3)