Accessing simulation results#
Simulation results are typically stored in datasets simulation or monitor objects Lumerical products. This article describes how you can access and process datasets and raw simulation data when using the PyLumerical.
For more information on how PyLumerical translates basic data types and best practices when transferring data, see the article on Passing data, for more information on Lumerical datasets, see the Lumerical Knowledge Base article Introduction to lumerical datasets.
Accessing datasets#
Lumerical products package relevant results in datasets so that you can readily visualize and explore them. You can use the getresult method to retrieve these datasets into the Python workspace.
PyLumerical retrieves datasets as dictionaries, with keys associated with various attributes and parameters.
Dictionaries converted from datasets have a special metadata key Lumerical_dataset which contains identifier values, this key preserves their structure when performing a roundtrip back to the Lumerical environment.
When passing a dictionary from Python to Lumerical, PyLumerical converts it into a generic structure, unless it has the metadata element.
Attributes and parameters are both stored as numpy.ndarray. Parameters are 1-D arrays that acts as a list of parameters.
For attributes, the dimension of the array depends on the type of dataset, the type of data, and the number of parameters.
Dataset Type |
Attribute Dimensions |
|---|---|
Matrix Dataset |
Dimensions depend on type of attribute:
where \(N_{p_i}\) is the length of the \(i\)th parameter. |
Rectilinear Dataset |
Dimensions depend on type of attribute:
where \(N_k\), \(k\) = \(x\), \(y\), \(z\) are the lengths of the coordinate vectors, and \(N_{p_i}\) is the length of the \(i\)th parameter. If the dataset is 2D or 1D, then there are singleton dimensions, so that one of \(N_k\) = 1. |
Unstructured Dataset |
Dimensions depend on type of attribute:
where \(N_N\) is the number of elements in the unstructured grid.
An extra attribute for the grid connectivity array,
|
Note
You can remove singleton dimensions with the pinch command in Lumerical or numpy.squeeze() in numpy.
Example
The following example uses an example file ‘fdtd_file.fsp’ created using the following script.
1from collections import OrderedDict
2import ansys.lumerical.core as lumapi
3with lumapi.FDTD() as fdtd:
4 fdtd.addfdtd(dimension="2D", x=0.0e-9, y=0.0e-9, x_span=3.0e-6, y_span=1.0e-6)
5 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)
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)
7 fdtd.addmesh(dx=10.0e-9, dy=10.0e-9, x=0., y=0., x_span=0.4e-6, y_span=0.4e-6)
8 fdtd.addtime(name="time", x=0.0e-9, y=0.0e-9)
9 fdtd.addprofile(name="profile", x=0., x_span=3.0e-6, y=0.)
10
11 # Dict ordering is not guaranteed, so if there properties dependent on other properties an ordered dict is necessary
12 # In this case 'override global monitor settings' must be true before 'frequency points' can be set
13 props = OrderedDict([("name", "power"),
14 ("override global monitor settings", True),
15 ("x", 0.),("y", 0.4e-6),("monitor type", "linear x"),
16 ("frequency points", 10.0)])
17
18 fdtd.addpower(properties=props)
19 fdtd.save("fdtd_file.fsp")
The following script uses this file to obtain rectilinear datasets.
1import ansys.lumerical.core as lumapi
2with lumapi.FDTD('fdtd_file.fsp') as fdtd:
3 fdtd.run()
4 # Return 2 different types of rectilinear datasets
5 T, time = fdtd.getresult("power", "T"), fdtd.getresult("time","E")
6
7print('Transmission result T is type', type(T),' with keys', str(T.keys()) )
8print('Time monitor result E is type', type(time),' with keys', str(time.keys()) )
Returns
1Transmission result T is type <class 'dict'> with keys dict_keys(['lambda', 'f', 'T', 'Lumerical_dataset'])
2Time monitor result E is type <class 'dict'> with keys dict_keys(['t', 'x', 'y', 'z', 'E', 'Lumerical_dataset'])
The following script creates a p-n junction in Lumerical Multiphysics, and returns an unstructured dataset related to its doping.
1from collections import OrderedDict
2import ansys.lumerical.core as lumapi
3with lumapi.DEVICE() as device:
4 # Create Simulation region
5 device.addsimulationregion(name = "SimRegion", dimension = "2D Y-Normal", x_span = 1.5e-6, z_span = 0.5e-6)
6 device.addchargesolver(name = "CHARGE", simulation_region = "SimRegion")
7
8 # Add materials
9 device.addmodelmaterial(name = "Silicon")
10 device.addmaterialproperties("CT","Si (Silicon)")
11
12 # Add Geometry
13 device.addrect(name = "junction", x_span = 2e-6, y_span = 1e-6, z_span = 0.5e-6, material = "Silicon")
14
15 # Add Doping
16 device.adddope(name ="n dope", x_min = -1e-6, x_max = 0, dopant_type = "n", concentration = 1e16)
17 device.adddope(name ="p dope", x_min = 0, x_max = 1e-6, dopant_type = "p", concentration = 1e16)
18
19 # Add Contacts
20 prop_n_contact = OrderedDict([("name", "n_contact"), ("surface type", "simulation region"), ("x min", True)])
21 device.addelectricalcontact(properties = prop_n_contact)
22
23 prop_p_contact = OrderedDict([("name", "p_contact"), ("surface type", "simulation region"), ("x max", True)])
24 device.addelectricalcontact(properties = prop_p_contact)
25
26 # Save File
27 device.save("UnstructuredDatasetTest.ldev")
28
29 # mesh and get doping results
30 device.mesh()
31 unstructured_result = device.getresult("CHARGE","grid")
32
33 print(f"unstructured_result is of type {type(unstructured_result)} and contains {unstructured_result.keys()}")
Returns
1unstructured_result is of type <class 'dict'> and contains dict_keys(['area', 'ID', 'x', 'y', 'z', 'connectivity', 'N', 'Lumerical_dataset'])
Accessing raw data#
Raw data from monitors are results in their raw, matrix form. You can also pass these results to the Python workspace using the getdata command.
PyLumerical retrieves raw data from Lumerical products as numpy.ndarray objects.
The length to each dimension of the returned array depends on whether the raw data was originally an attribute or parameter. These dimensions follow the dimensions for attributes and parameters described in the “Accessing dataset” section.
Example
The following example uses the FDTD project file “fdtd_file.fsp” created above and accesses raw data stored in the profile monitor.
1import ansys.lumerical.core as lumapi
2with lumapi.FDTD('fdtd_file.fsp') as fdtd:
3 fdtd.run()
4
5 # Return raw E field data
6 Ex = fdtd.getdata("profile","Ex")
7 f = fdtd.getdata("profile","f")
8 x = fdtd.getdata("profile","x")
9 y = fdtd.getdata("profile","y")
10
11print('Frequency field profile data Ex is type', type(Ex),' with shape', str(Ex.shape))
12print('Frequency field profile data f is type', type(f), 'with shape', str(f.shape))
13print('Frequency field profile data x is type', type(x), 'with shape', str(x.shape))
14print('Frequency field profile data y is type', type(y), 'with shape', str(y.shape))
Returns
1Frequency field profile data Ex is type with shape (99, 59, 1, 5)
2Frequency field profile data f is type with shape (5, 1)
3Frequency field profile data x is type with shape (99, 1)
4Frequency field profile data y is type with shape (59, 1)