When driving Lumerical's tools from the Python API there is a connection established between the environments, but they do not share a workspace. Instead, as variables are passed back and forth an exact copy is created according to the type conversion defined in getv(), and putv(). As of 2020a R4 typical transfer speeds are about 300 MBs, and reduced the memory overhead required to transfer data to 3x. This does not present an issue in terms of fidelity nor does it typically present a bottleneck in terms of speed; however, when working with very large datasets it may be important to take this into consideration if efficiency is imperative.
A quick reference guide for translated datatypes.
Lumerical |
Python |
---|---|
String |
string |
Real |
float |
Complex |
np.array |
Matrix |
np.array |
Cell array |
list |
Struct |
dictionary |
Dataset |
dictionary |
Users of the API will often be interested in returning the following data types from monitors.
Raw Data
When accessing the raw data from a simulations it is available as a matrix in Lumerical and will be returned as a numpy array when passed to the Python environment.
The size of the matrices will be consistent with the lengths of the associated parameters.
- Attribute: The actual data of a dataset. For example the electric field components Ex, Ey, Ez are the attributes of a field profile monitor.
- Parameter: The associated position vectors of a dataset. For example x, y, z, and f could be the parameters of a field profile monitor.
Matrix dataset
- Scalar attribute: [\(N_{p1}; N_{p2}; ...; N_{pn}\)]
- Vector attribute: [\(N_{p1}; N_{p2}; ...; N_{pn}; 3 \)]
where \(N_{pi} \) is the length of the \( i^{th} \) parameter.
To access the raw monitor data use the getdata(), and Python squeeze or pinch() method to remove singleton dimensions.
with lumapi.FDTD() as fdtd:
fdtd.addfdtd(dimension="2D", x=0.0e-9, y=0.0e-9, x_span=3.0e-6, y_span=1.0e-6)
fdtd.addgaussian(name = 'source', x=0., y=-0.4e-6, injection_axis="y", waist_radius_w0=0.2e-6, wavelength_start=0.5e-6, wavelength_stop=0.6e-6)
fdtd.addring( x=0.0e-9, y=0.0e-9, z=0.0e-9, inner_radius=0.1e-6, outer_radius=0.2e-6, index=2.0)
fdtd.addmesh(dx=10.0e-9, dy=10.0e-9, x=0., y=0., x_span=0.4e-6, y_span=0.4e-6)
fdtd.addtime(name="time", x=0.0e-9, y=0.0e-9)
fdtd.addprofile(name="profile", x=0., x_span=3.0e-6, y=0.)
# Dict ordering is not guaranteed, so if there properties dependant on other properties an ordered dict is necessary
# In this case 'override global monitor settings' must be true before 'frequency points' can be set
props = OrderedDict([("name", "power"),
("override global monitor settings", True),
("x", 0.),("y", 0.4e-6),("monitor type", "linear x"),
("frequency points", 10.0)])
fdtd.addpower(properties=props)
fdtd.save("fdtd_file.fsp")
fdtd.run()
#Return raw E field data
Ex = fdtd.getdata("profile","Ex")
f = fdtd.getdata("profile","f")
x = fdtd.getdata("profile","x")
y = fdtd.getdata("profile","y")
print('Frequency field profile data Ex is type', type(Ex),' with shape', str(Ex.shape ))
print('Frequency field profile data f is type', type(f), 'with shape', str(f.shape ))
print('Frequency field profile data x is type', type(x), 'with shape', str(x.shape ))
print('Frequency field profile data y is type', type(y), 'with shape', str(y.shape ))
Returns
Frequency field profile result Ex is type <class 'numpy.ndarray'> with shape (101, 61, 1, 5)
Frequency field profile result f is type <class 'numpy.ndarray'> with shape (5, 1)
Frequency field profile result x is type <class 'numpy.ndarray'> with shape (101, 1)
Frequency field profile result y is type <class 'numpy.ndarray'> with shape (61, 1)
Datasets
Datasets are relevant results that have been packaged in a form that makes it possible to readily visualize, and explore in Lumerical.
Rectilinear dataset
- Scalar attribute: [\(N_{\mathbf{x}}; N_{\mathbf{y}}; N_{\mathbf{z}}; N_{p1}; N_{p2}; ...; N_{pn}\)]
- Vector attribute: [\(N_{\mathbf{x}}; N_{\mathbf{y}}; N_{\mathbf{z}}; N_{p1}; N_{p2}; ...; N_{pn}; 3 \)]
- Tensor attribute: [\(N_{\mathbf{x}}; N_{\mathbf{y}}; N_{\mathbf{z}}; N_{p1}; N_{p2}; ...; N_{pn}; 9 \)]
where \(N_{\mathbf{k}}, \mathbf{k} = \mathbf{x},\mathbf{y},\mathbf{z} \) are the lengths of the coordinate vectors, and \(N_{pi} \) is the length of the \( i^{th} \) parameter. If the dataset is 2D or 1D then you will have singleton dimensions, so that one or multiple \(N_{\mathbf{k}} = 1\). These dimensions can be removed with the pinch command.
Unstructured spatial datasets are similar but contain the connectivity of the gridpoints as a spatial attribute. These are used extensively in the Finite Element solvers CHARGE, HEAT, FEEM, and DGTD.
Spatial datasets passed to the python environment will be converted to dictionaries, with keys associated to the various attributes and parameters. Since the attributes are are matrices they will converted to numpy arrays. Furthermore they will have a special metadata tag 'Lumerical_dataset' which allows their structure to be preserved when performing a roundtrips back to the Lumerical environment. When passing a dictionary from python to Lumerical it will be converted into an arbitrary unstructured dataset, unless it has the metadata section. Use the getresult() method to return datasets.
with lumapi.FDTD('fdtd_file.fsp') as fdtd:
#Return 2 different types of rectilinear datasets
T, time = fdtd.getresult("power", "T"), fdtd.getresult("time","E")
#Create an unstructured dataset
fdtd.eval('x = [0;1;2];y = [0;sqrt(3);0];z = [0;0;0];C = [1,3,2];ds = unstructureddataset(x,y,z,C);')
ds = fdtd.getv('ds')
print('Transmission result T is type', type(T),' with keys', str(T.keys()) )
print('Time monitor result E is type', type(time),' with keys', str(time.keys()) )
print('Unstructured dataset is type', type(ds),' with keys', str(ds.keys()) )
Returns
Transmission result T is type <class 'dict'> with keys dict_keys(['lambda', 'f', 'T', 'Lumerical_dataset'])
Time monitor result E is type <class 'dict'> with keys dict_keys(['t', 'x', 'y', 'z', 'E', 'Lumerical_dataset'])
Unstructured dataset is type <class 'dict'> with keys dict_keys(['x', 'y', 'z', 'connectivity', 'Lumerical_dataset'])