# Variable Descriptions

Descriptions of the variables stored in a simulation file. Variables are read back with
[`get`](../interface.md#get) (or, for grids, fields, shapes and whole profiles, with the typed accessors
[`get_grid`](file-management.md#get_grid), [`get_fields`](file-management.md#get_fields), [`get_shape`](file-management.md#get_shape) and [`get_profile`](file-management.md#get_profile)). Some
variables have an alias, a copy under an older name kept for compatibility. SHAPE stands
for a shape name and NAME for a profile name. [`inspect`](file-management.md#inspect) lists every name [`get`](../interface.md#get)
can read.

## How the simulation file is organized

A simulation file has two levels.

**Top-level variables** describe the file and the EME circuit: `EMode_simulation_file`,
`file_type`, `emode_version`, `materials`, `profiles`,
`propagation_resolution`, and, once the corresponding functions have run,
`sweep_data`, `S_matrix` (through `get('S_matrix')`), `response` and `sources`.
[`inspect`](file-management.md#inspect) returns their names, followed by the per-profile variables and settings
below. Names beginning with an underscore are internal and may change between versions.

**Profiles** live under the top-level `profiles` dictionary, one entry per cross-section.
`'_default'` is the working profile that [`settings`](setup.md#settings), [`shape`](setup.md#shape), [`mesh`](solver-analysis.md#mesh) and
[`FDM`](solver-analysis.md#FDM) act on unless `profile=` is given. [`label_profile`](solver-analysis.md#label_profile) saves a copy of it
under a name. [`FDM`](solver-analysis.md#FDM) with `profile=` saves its result under a name.
[`create_profile_set`](file-management.md#create_profile_set) groups profiles solved at different wavelengths into one
multi-wavelength profile, in which case per-profile results come back as a dictionary keyed
by wavelength. Every function that reads a profile takes `profile=NAME`: [`get`](../interface.md#get),
[`get_fields`](file-management.md#get_fields), [`get_grid`](file-management.md#get_grid), [`get_shape`](file-management.md#get_shape), [`get_profile`](file-management.md#get_profile),
[`confinement`](solver-analysis.md#confinement), [`effective_area`](solver-analysis.md#effective_area), [`group_index`](solver-analysis.md#group_index), [`orthogonality`](solver-analysis.md#orthogonality),
[`report`](solver-analysis.md#report), [`scattering`](solver-analysis.md#scattering), [`mesh`](solver-analysis.md#mesh), [`FDM`](solver-analysis.md#FDM), [`delete_profile`](file-management.md#delete_profile),
[`reset`](setup.md#reset), [`clear_field_data`](file-management.md#clear_field_data). [`reset`](setup.md#reset) and [`clear_field_data`](file-management.md#clear_field_data) act on
the profile they are given and leave every other profile alone.

One wavelength of a multi-wavelength profile is `profile='NAME.WAVELENGTH'`, for example
`get('effective_index', profile='tfln.1550')`. A member can also be named by its own name
(`'NAME.MEMBER'`) when that name is its own, as after [`create_profile_set`](file-management.md#create_profile_set). A name
that several members share, such as the `'_default'` that every member of a labeled
multi-wavelength profile keeps, raises an error naming the `NAME.WAVELENGTH` of each.

**Settings** (window, resolution, boundary condition, PML, …) are part of the profile.
`get(key, profile=NAME)` returns any of them, under its current name or an older alias,
and `get_profile(NAME).settings` returns them all at once.

## Per-profile variables

Read with `get(key, profile=NAME)` (default `NAME='_default'`). A multi-wavelength
profile (a profile set) returns a `dict[float, ...]` of the same, keyed by wavelength.

<a id="term-background_material"></a>

background_material
: (*float* or *str*) The background material of the profile’s simulation window, setting the default material where no shapes are defined.

<a id="term-effective_index"></a>

effective_index
: (*list*) The real part of the effective index for each mode.
  <br/>
  Alias: `n_eff`

<a id="term-Ex-Ey-Ez-Hx-Hy-Hz"></a>

Ex, Ey, Ez, Hx, Hy, Hz
: (*complex arrays*) The electric (E [V/nm]) and magnetic (H [A/nm]) fields in the x-, y-, and z-directions. These calculated fields are interpolated to the center point of each mesh grid (defined by `xc` and `yc`). The fields are normalized to the equation below.
  <br/>
  $$
  \frac{1}{2} \mathrm{Re} \iint \left( \vec E \times \vec H^* \right) \! \cdot \! \hat{z} \, \mathrm{d}x \, \mathrm{d}y = 1 \, \mathrm{W}
  <br/>
  $$
  <br/>
  Deprecated: fetching these through `get()` (rather than [`get_fields`](file-management.md#get_fields)) prints a deprecation warning.

<a id="term-Fx-Fy"></a>

Fx, Fy
: (*complex arrays*) Raw fields that are solved. They either correspond to the electric or magnetic fields depending on `field_to_solve`. However, these raw fields are defined on the Yee mesh grid, not the center points of the mesh grid. An internal function extracts all other field components from `Fx`, `Fy`, `permittivity`, and `permeability`.

<a id="term-Gx-Gy"></a>

Gx, Gy
: (*complex arrays*) The auxiliary longitudinal raw field components present for a bend or an anisotropic solve. Present only when the corresponding basis actually carries them.

<a id="term-convergence"></a>

convergence
: (*dict*) The last [`converge`](solver-analysis.md#converge) run on this profile, as plain data: the arguments it ran with, its `status`, the settings it chose (`chosen`), one `stages` entry per setting it varied and one `history` row per solve (the setting’s value, the target quantity, its change and estimated error, and the solve time).

<a id="term-confinement_window"></a>

confinement_window
: (*list*) The confinement factor for each specified mode is saved under this variable only when the confinement region is specified with a list of vertices, instead of a specific shape.

<a id="term-effective_area"></a>

effective_area
: (*list*) The effective area of each waveguide mode in units of square microns ($\mu \mathrm{m}^2$), calculated by the following equation.
  <br/>
  $$
  A_\mathrm{eff} = \frac{\left( \iint \left| \vec E \right|^2 \, \mathrm{d}x \, \mathrm{d}y \right)^2}{\iint \left| \vec E \right|^4 \, \mathrm{d}x \, \mathrm{d}y}
  <br/>
  $$

<a id="term-extent-pml_extent"></a>

extent, pml_extent
: (*list*) `[xmin, xmax, ymin, ymax]` of the full simulation window, and of the window with the pml region excluded.

<a id="term-group_index"></a>

group_index
: (*list*) The group refractive index calculated for each mode.
  <br/>
  Alias: `n_g`

<a id="term-loss_dB_per_m"></a>

loss_dB_per_m
: (*float*) [dB/m] The power loss coefficient ($\alpha$), which relates to the imaginary part of the effective index ($\kappa$) by the following equation with the wavelength ($\lambda$).
  <br/>
  Alias: `alpha`
  <br/>
  $$
  \kappa = \frac{\alpha \lambda}{(4 \pi) 10 \, \mathrm{log}_{10}(e)} \approx \frac{\alpha \lambda}{54.575}
  <br/>
  $$
  <br/>
  With `include_scattering=True` it is the total loss, the material loss above plus the interfacial scattering loss of the rough shapes. `scattering_loss` is the part that is scattering. Without `include_scattering` it is the material loss alone, even after a call to `scattering()`.
  <br/>
  Loss is positive and gain negative. Under a PML, a guided mode of a lossless structure can show a small loss or a small gain (a negative `loss_dB_per_m`). Neither is physical. It is the error from truncating the mode’s evanescent tail at the window and its PML, of the same size as the error in its effective index, and it vanishes as the window widens or the PML thickens (`converge(setting='pml')`). The solve warns when such a mode gains more than 1e-6 of its index.

<a id="term-maximum_overlap"></a>

maximum_overlap
: (*float*) Largest overlap in the mode list, calculated from the `orthogonality()` function.

<a id="term-overlap"></a>

overlap
: (*list*) The overlap integral in `overlap` uses the following formula to calculate the modal excitation of $\vec E_2$ by $\vec E_1$.
  <br/>
  > Coldren, Larry A., Scott W. Corzine, and Milan L. Mashanovitch, ‘’Diode lasers and photonic integrated circuits,’’ John Wiley & Sons, 2012.
  $$
  \mathrm{overlap} = \frac{4 n_\mathrm{eff,1} n_\mathrm{eff,2}}{(n_\mathrm{eff,1} + n_\mathrm{eff,2})^2} \frac{\left| \iint \vec E_2^* \cdot \vec E_1 \, \mathrm{d}x \, \mathrm{d}y \right|^2}{\iint \left| \vec E_1 \right|^2 \, \mathrm{d}x \, \mathrm{d}y \, \iint \left| \vec E_2 \right|^2 \, \mathrm{d}x \, \mathrm{d}y}
  <br/>
  $$
  <br/>
  Stored on the profile named by `profile_b`. It holds the result of the latest [`overlap`](solver-analysis.md#overlap) call against that profile, and `overlaps` keeps them all.

<a id="term-overlaps"></a>

overlaps
: (*list*) One record per [`overlap`](solver-analysis.md#overlap) call against this profile (as `profile_b`), each a dict with `simulation_name_a`, `profile_a`, `mode_a`, `mode_b` and `overlap`. Repeating the same pair of modes replaces its record.

<a id="term-permittivity-permeability"></a>

permittivity, permeability
: (*list*) The permittivity and permeability arrays are defined by `mesh` from the current shapes and settings. Each is a list of arrays defining the corresponding parameters in the x-, y-, and z-directions.

<a id="term-PML_indices"></a>

PML_indices
: (*list*) Indices of modes that carry less than 75% of their power inside the simulation window. These are modes of the pml (absorbing) region rather than of the device. Present only when the profile was solved with a pml. See `window_confinement`, and `remove_pml_modes_bool`/`pml_seed_bool` under Settings.

<a id="term-scattering_sum-scattering_loss"></a>

scattering_sum, scattering_loss
: (*list*) Total per-mode scattering loss [dB/m] summed over shape edges: `scattering_sum` is a list of per-shape contributions, `scattering_loss` their sum. Populated after `scattering()` runs. With `include_scattering=True`, `loss_dB_per_m` includes `scattering_loss`.

<a id="term-shapes"></a>

shapes
: (*list*) The list of `Shape` objects making up the profile, background included. Prefer [`get_shape`](file-management.md#get_shape) to read a single shape’s attributes and metadata.

<a id="term-Sx-Sy-Sz"></a>

Sx, Sy, Sz
: (*complex arrays*) [W/nm<sub>2</sub>] The time-averaged Poynting vector, $\frac{1}{2} \vec E \times \vec H^*$, in the x-, y-, and z-directions. Its real part integrates to the mode’s power, 1 W.

<a id="term-TE_fraction"></a>

TE_fraction
: (*list*) Fractions representing how much the mode is like a TE mode, calculated with the following equation.
  <br/>
  $$
  \mathrm{{TE_fraction}} = \frac{\iint \left| \vec E_\mathrm{x} \right|^2 \, \mathrm{d}x \, \mathrm{d}y}{\iint \left| \vec E_\mathrm{x} \right|^2 + \left| \vec E_\mathrm{y} \right|^2 \, \mathrm{d}x \, \mathrm{d}y}
  <br/>
  $$

<a id="term-TE_indices-TM_indices"></a>

TE_indices, TM_indices
: (*list*) Indices for the corresponding TE or TM modes in the modes list.

<a id="term-wavelength"></a>

wavelength
: (*float*) [nm] Free-space wavelength.

<a id="term-window_confinement"></a>

window_confinement
: (*list*) Fraction of each mode’s power inside the simulation window (inset by one grid cell on every side), only present when the profile has a pml. A mode below 75% is a mode of the absorbing region rather than of the device (the modes that `remove_pml_modes_bool` discards and `PML_indices` designates).

<a id="term-xc-yc"></a>

xc, yc
: (*complex arrays*) Cell-center coordinates of the mesh grid, in the x- and y-directions. These can be complex when pml layers are introduced.
  <br/>
  Deprecated: `x`, `y`. Read through [`get_grid`](file-management.md#get_grid) instead.

## Simulation-level variables

Read with `get(key)` (no `profile=`). Listed by [`inspect`](file-management.md#inspect).

<a id="term-emode_version"></a>

emode_version
: (*str*) The version of EMode that wrote the simulation file.

<a id="term-EMode_simulation_file"></a>

EMode_simulation_file
: (*str*) The file name the simulation was created with. It also serves as a marker that this is a valid EMode simulation file.

<a id="term-file_type"></a>

file_type
: (*str*) The simulation file’s extension, `'.eph'`.

<a id="term-serialized"></a>

serialized
: (*bool*) Internal bookkeeping for the file’s on-disk (de)serialization state.

<a id="term-eme_scattering"></a>

eme_scattering
: (*bool*) Legacy key, found only in simulation files written before EMode 1.0.5, which still load. It has no effect: EME scattering is controlled by `EME_settings(apply_scattering=...)`, and `settings(eme_scattering=...)` is deprecated and no longer stores it. On a newer file `get('eme_scattering')` returns False with a deprecation warning.

<a id="term-materials"></a>

materials
: (*list*) Names of every material in the database, built-in and user-added. A user-added material’s own properties are returned by `get(NAME)`. See `user_material_NAME` below.

<a id="term-priority_indices"></a>

priority_indices
: (*list*) A list of indices corresponding to the priorities of the shapes in the current profile.

<a id="term-profiles"></a>

profiles
: (*dict*) The named profiles saved in this file (see “How the simulation file is organized” above). It does not include `'_default'`.

<a id="term-propagation_resolution"></a>

propagation_resolution
: (*float*) [nm] Sampling resolution used along the propagation direction for EME field reconstruction.

<a id="term-pulse_response"></a>

pulse_response
: (*PulseResponse*) The spectrum of every tracked mode along the chain from the most recent [`EME`](eme.md#EME) or [`pulse_propagate`](eme.md#pulse_propagate) with a `PulsedSource` excitation. It is returned by `get('pulse_response')` (EMode<sub>3D</sub> only). See [`PulseResponse`](eme.md#PulseResponse).

<a id="term-pulsed_source"></a>

pulsed_source
: (*PulsedSource*) The declared pulsed excitation. It is returned by `get('pulsed_source')`.

<a id="term-response"></a>

response
: (*CircuitResponse*) The power-dependent nonlinear response from the most recent EME solve with a declared excitation. It is returned by `get('response')` and also carries `trajectories`, the forward amplitudes recorded along each $\chi^{(2)}$ slice, read with `power_vs_z(wavelength)` or `amplitude_vs_z(wavelength)`.

<a id="term-S_matrix"></a>

S_matrix
: (*SMatrix*) The scattering matrix from a solved EME chain. It is returned by `get('S_matrix')` (EMode<sub>3D</sub> only).

<a id="term-sources"></a>

sources
: (*list*) The declared excitation sources for the EME chain. It is returned by `get('sources')`.

<a id="term-sweep_data"></a>

sweep_data
: (*dict*) Results from the most recent `sweep()` call.

<a id="term-user_material_NAME"></a>

user_material_NAME
: (*str*) The name of a user defined material.

## Settings

Read with `get(key, profile=NAME)`, like the per-profile variables above. A
multi-wavelength profile returns a `dict[float, ...]` keyed by wavelength. A setting
reads back under the name it was set by, so an alias given to [`settings`](setup.md#settings) (such as
`radius` or `N_pml`) works here too. Each is also a field of
`get_profile(NAME).settings`.

<a id="term-bend_radius"></a>

bend_radius
: (*float*) [nm] Bend radius of the waveguide. A value of 0 indicates that no bend is applied.
  <br/>
  Alias: `radius`

<a id="term-bend_method"></a>

bend_method
: (*str*) How a nonzero `bend_radius` is solved. `'cylindrical'` (the default) adds the bend factor 1 + x/R to the mode solver. `'TO'` solves the straight cross-section with its material transformed by the bend’s conformal map (transformation optics). Both work with the FDM and the FEM. The two methods’ effective indices differ by about 6e-4 at R = 10 um, and their bend losses by about 1 % on a fine grid. With a PML, a bend’s spectrum starts with PML modes, so set `max_effective_index` just above the guided mode. An under-resolved bend shows up as spurious bend loss. The ‘Bend Mode Solvers’ example compares the four combinations.

<a id="term-boundary_condition"></a>

boundary_condition
: (*str*) Boundary condition for the simulation window. A value of 0 indicates a metal boundary (driving all fields to zero at the boundary) and A or S indicate anti-symmetric or symmetric Ex. The first character indicates south boundary condition and the second character indicates the west boundary condition. `get('boundary_condition')` returns the string as given (for example `'TE'`), and `BC` below is the resolved boundary condition.
  <br/>
  Alias: `BC`, as a [`settings`](setup.md#settings) argument only. `get('BC')` returns the resolved value.

<a id="term-BC"></a>

BC
: (*str*) A copy of the boundary_condition before running FDM(). After running FDM(), this variable represents the actual boundary condition string as a combination of ‘0’, ‘A’, or ‘S’. For example, setting the boundary_condition to ‘TE’ and running FDM() will result in BC changing to either ‘SS’, ‘0S’, ‘S0’, or ‘00’, depending on the index profile cross-section symmetry.

<a id="term-expansion_resolution"></a>

expansion_resolution
: (*list*) List of the desired mesh step size in the x- and y-directions in the expanded regions around the perimeter of the simulation window.

<a id="term-expansion_size"></a>

expansion_size
: (*list*) List of the size of the expanded regions in the x- and y-directions.

<a id="term-fem_max_dofs"></a>

fem_max_dofs
: (*int*) The FEM solver stops refining before the problem exceeds this many unknowns.

<a id="term-fem_max_refinements"></a>

fem_max_refinements
: (*int* or *str*) Maximum number of adaptive FEM refinement passes. 0 disables refinement. `'converge'` refines until the extrapolated effective indices settle to 1e-8, as described under [`settings`](setup.md#settings).

<a id="term-fem_mesh_wavelength"></a>

fem_mesh_wavelength
: (*float*) [nm] The FEM solver builds and refines its mesh at this wavelength and solves every wavelength on it. 0 meshes each solve at its own wavelength.

<a id="term-fem_min_angle"></a>

fem_min_angle
: (*float*) [degrees] Minimum triangle angle of the FEM mesh, at most 34.

<a id="term-fem_neff_tolerance"></a>

fem_neff_tolerance
: (*float*) The FEM solver stops refining once no requested mode’s effective index moves by more than this relative amount.

<a id="term-fem_order"></a>

fem_order
: (*int*) FEM element order, 1 or 2. Order 2 converges much faster in the effective index.

<a id="term-fem_points_per_wavelength"></a>

fem_points_per_wavelength
: (*float*) Initial FEM mesh density, as mesh points per wavelength in each material. [`converge`](solver-analysis.md#converge) chooses it for the FEM with `setting='resolution'`.

<a id="term-fem_refine_fraction"></a>

fem_refine_fraction
: (*float*) Share of the estimated error each adaptive FEM refinement pass targets, in (0, 1].

<a id="term-fem_smooth_passes"></a>

fem_smooth_passes
: (*int*) Passes of angle smoothing on the first FEM mesh. 0 turns it off.

<a id="term-field_to_solve"></a>

field_to_solve
: (*str*) Desired transverse field component to solve: either ‘Et’ or ‘Ht’.

<a id="term-fLanczos"></a>

fLanczos
: (*int* or None) Size of the eigensolver’s Krylov subspace as a multiple of `num_modes`. None, the default, is automatic: 5 up to 10 modes, and a smaller multiple past 10 modes (`2 num_modes + 31` vectors in all, past 5 modes on the anisotropic solver, which searches twice `num_modes`). An integer is used exactly. Set with [`FDM`](solver-analysis.md#FDM). A file saved before 1.0.8 holds 5, which is used as written.

<a id="term-generate_chi2"></a>

generate_chi2
: (*bool*) Generate the second-order nonlinear susceptibility ($\chi^{(2)}$) tensor for the simulation window when meshing.

<a id="term-include_heat"></a>

include_heat
: (*bool*) Include the temperature change from the most recent `heat()` solve in the material properties.

<a id="term-include_scattering"></a>

include_scattering
: (*bool*) Compute the interfacial scattering loss of every rough shape after each solve of this profile. Set with `settings(include_scattering=True)`.

<a id="term-max_effective_index"></a>

max_effective_index
: (*float*) Upper limit for the effective index, which is the eigensolver’s shift unless `pml_seed_bool` derives one automatically.

<a id="term-mesh_complete_bool"></a>

mesh_complete_bool
: Removed. Use `get_profile(NAME).status.meshed`.

<a id="term-num_modes"></a>

num_modes
: (*int*) Total number of modes to solve. [`converge`](solver-analysis.md#converge) chooses it with `setting='modes'`.

<a id="term-num_pml_layers"></a>

num_pml_layers
: (*int* or *list*) Either an integer or a list of integers indicating the number of perfectly matched layers for all or each boundary: [North, South, East, West]. The FDM’s pml is this many grid cells thick where `pml_thickness` is 0. When neither is set (the default), the FDM’s pml is as thick as its imaginary depth, 2.27 um at 1550 nm, and never fewer than 10 cells. For the FEM it refines the pml’s mesh (unset or 10 meshes it at its material’s resolution, 20 twice as finely), and it does not set the thickness.

<a id="term-pml_thickness"></a>

pml_thickness
: (*float* or *list*) Either a float or a list of floats indicating the perfectly matched layer thickness in nm for all or each boundary: [North, South, East, West]. In the FDM, 0 means the boundary uses `num_pml_layers` instead, or the pml’s imaginary depth when that is not set either. The FEM delivers exactly this thickness, and where it is 0 the FEM chooses twice the pml’s imaginary depth (see `pml_thickness` under [`settings`](setup.md#settings)). Unlike a layer count, this holds the absorber’s physical size fixed as the resolution changes. [`converge`](solver-analysis.md#converge) chooses it with `setting='pml'`.

<a id="term-pml_alpha_max"></a>

pml_alpha_max
: (*float*) The complex-frequency-shifted (CFS) term of the pml profile, where 0 disables it.

<a id="term-pml_kappa_max"></a>

pml_kappa_max
: (*float*) The maximum real coordinate stretch of the pml profile, reached at the outer pml face, in both the FDM and the FEM.

<a id="term-pml_NSEW_bool"></a>

pml_NSEW_bool
: (*list*) List of booleans indicating if a perfectly matched layer (pml) boundary condition is applied to each boundary: [North, South, East, West].

<a id="term-pml_order"></a>

pml_order
: (*float*) The polynomial grading exponent of the pml stretch profile.

<a id="term-pml_reflection"></a>

pml_reflection
: (*float*) The target round-trip reflection that the pml is designed for, which sets the maximum pml conductivity.

<a id="term-pml_seed_bool"></a>

pml_seed_bool
: (*bool*) Seed the pml eigensolve with the fundamental mode of the same structure solved without a pml, so the guided fundamental lands at mode 0 without a hand-tuned `max_effective_index`.

<a id="term-remove_pml_modes_bool"></a>

remove_pml_modes_bool
: (*bool*) Indicates whether or not to automatically remove artificial modes found in the pml layers.

<a id="term-shape_list-shape_materials"></a>

shape_list, shape_materials
: Removed. Use `get_profile(NAME).shapes` (or the per-profile `shapes` variable above).

<a id="term-solve_workers"></a>

solve_workers
: (*int or str*) How many profiles a batch of solves solves at once, each in its own process: a taper’s slices, a wavelength scan, the points of a multi-key [`sweep`](solver-analysis.md#sweep) and the nodes of an interpolated sweep. `'auto'` (the default) uses as many workers as there are cores divided by two, fewer if the memory the first solve needs allows fewer, and solves in this process when the remaining work would take under about 10 seconds. 1 solves one at a time. Rule of thumb: `solve_workers` times `solver_threads` about equals the number of cores, memory permitting. The `EMODE_SOLVE_WORKERS` environment variable sets it while it is `'auto'`. A session with a material added by [`add_material`](setup.md#add_material) solves in this process. On an 8-core machine four workers with two threads each solved about twice as many mode problems a second as one process with eight threads.

<a id="term-solver"></a>

solver
: (*str*) The mode solver for this profile: `'default'`, `'FDM'`, `'FEM'` or `'bessel'`. `'bessel'` is the exact solver for one round step-index core (an `'ellipse'` of equal width and height) of a lossless, isotropic material in a uniform cladding. It solves the Bessel-function eigenvalue equations to machine precision, sees a true circle rather than a polygon, and returns the guided modes only. `'default'` is the Bessel solver for such a fiber when it guides `num_modes` modes in the symmetry the boundary condition keeps and no PML is set, and the FDM otherwise. The FEM runs only when asked for, with `solver='FEM'` or `FEM()`.

<a id="term-solver_threads"></a>

solver_threads
: (*int*) Number of threads the sparse solver uses to factor this profile’s systems. 0, the default, lets the solver choose, up to every logical core and at most 16. The environment variable `EMODE_SOLVER_THREADS` sets it while it is 0. The eigensolver’s iterations run in one thread, so threads beyond two or four per solve buy little. Several solves at once (`solve_workers`) use the cores better, so keep `solve_workers` times `solver_threads` about equal to the number of cores.

<a id="term-sparse_solver"></a>

sparse_solver
: (*str*) The sparse direct solver for this profile’s solves: `'auto'`, `'rslab'` or `'pardiso'`. `'auto'` uses rslab on every installer. `'pardiso'` uses MKL PARDISO, which the Intel Mac, Windows and Linux installers still include (all but the slim Linux-rslab build).

<a id="term-subpixel_avg"></a>

subpixel_avg
: (*bool*) Use sub-pixel averaging of the permittivity and permeability at shape boundaries.

<a id="term-subpixel_tensor"></a>

subpixel_tensor
: (*bool or ‘auto’*) Add the off-diagonal terms of the sub-pixel average at slanted walls, default `'auto'`. A wall that is neither horizontal nor vertical (a ring, a circular core, an angled sidewall) couples the field components across it. The default keeps only the diagonal of that coupling, which is already second order in the grid spacing. `True` keeps all of it and is more accurate on curved and angled walls, at the cost of an anisotropic solve: the permittivity becomes a full tensor, so the solve takes longer, cannot use a symmetry wall in `boundary_condition` and needs an EMode3D license. A mesh with `subpixel_tensor=True` and a `boundary_condition` that folds raises an error. `'auto'` turns the terms on when the profile has a curved or slanted wall (a circle, an ellipse, or a run of slanted edges longer than one cell), the session has an EMode3D license, and the `boundary_condition` does not fold an axis. Otherwise it keeps the diagonal rule, so EMode2D sessions are unchanged. The choice is logged once at info level with its reason. `False` always keeps the diagonal rule.

<a id="term-tolerance"></a>

tolerance
: (*float*) Numerical tolerance for convergence of the effective indices.

<a id="term-window_height"></a>

window_height
: (float) [nm] Total height (y-direction) of the simulation window. The mesh is a whole even number of `y_resolution` cells, starting at the window’s bottom (y = 0), so a layer stacked from there in whole cells has its faces on grid lines. A window that is not a whole even number of cells grows to the next even count at the top. Under a y fold of `boundary_condition` it grows by the same amount above and below instead, so its middle, where the symmetry wall sits, stays a grid line. `settings` warns when the window grows, and `get('window_height')` then reads the height that was meshed. A `window_height` that is a multiple of twice `y_resolution` is meshed as given. The FEM meshes the same window. [`converge`](solver-analysis.md#converge) chooses it with `setting='window'`.

<a id="term-window_width"></a>

window_width
: (float) [nm] Total width (x-direction) of the simulation window. The mesh is a whole even number of `x_resolution` cells with a grid line at x = 0, the window’s middle. A width that is not grows to the next even count, by the same amount on each side, which keeps x = 0 a grid line, and `get('window_width')` then reads the width that was meshed. [`converge`](solver-analysis.md#converge) chooses it with `setting='window'`.

<a id="term-x_resolution-y_resolution"></a>

x_resolution, y_resolution
: (*float* or *str*) [nm] Mesh grid step in the x- and y-directions, or `'auto'` (a graded grid that matches the uniform 10 nm grid’s accuracy with fewer cells) or `'converge'` (a sequence of graded grids extrapolated to the converged effective index), as they were set. [`converge`](solver-analysis.md#converge) chooses a uniform step with `setting='resolution'`.

<a id="term-resolution_report"></a>

resolution_report
: (*dict*) What the last solve under `x_resolution='converge'`, or an FEM solve under `fem_max_refinements='converge'`, did: `'effective_index'` (each mode’s extrapolated index), `'estimated_error'` (each mode’s estimated error), `'order'` (each mode’s observed convergence order), `'status'` (`'converged'` when every estimated error is below `'tolerance'`, 1e-8, otherwise why it stopped), `'cap'` (the limit it stopped at, None when converged), `'finest_resolution'`, `'history'` (each grid’s resolution, cell count, effective indices and seconds, and for the FEM each mesh’s shortest edge, unknowns, elements, effective indices and seconds) and `'seconds'`. For the FEM, `'finest_resolution'` is the finest mesh’s shortest edge in nm and `'order'` the order in the mesh size the last three meshes show.

## Shape attributes

Read with [`get_shape`](file-management.md#get_shape) (or `get('shape_SHAPE')`), which returns a Shape object with
these attributes, plus a `metadata` dict populated once `scattering()`/`confinement()`
have run for that shape.

<a id="term-SHAPE-correlation_length"></a>

SHAPE[‘correlation_length’]
: (*list*) A list of two values describing the correlation length of the roughness on the vertical and horizontal edges of the shape.
  <br/>
  Alias: `Lc_nm`

<a id="term-SHAPE-fill_material"></a>

SHAPE[‘fill_material’]
: (*float* or *str*) Either a value or a material name to define the refractive index in the etched region of a ‘planar’ shape.

<a id="term-SHAPE-geometry"></a>

SHAPE[‘geometry’]
: (*dict*) A dictionary of the parameters of the shapes geometry

<a id="term-SHAPE-geometry-etch_depth"></a>

SHAPE[‘geometry’][‘etch_depth’]
: (*float*) The etch depth associated with a ‘planar’ shape that also has a defined `SHAPE['geometry']['mask']`. The shape will have a thickness outside the mask definition equal to the difference between the `SHAPE['geometry']['height']` and `SHAPE['geometry']['etch_depth']` (or zero if this is negative).

<a id="term-SHAPE-geometry-height"></a>

SHAPE[‘geometry’][‘height’]
: (*float*) Maximum size of the shape in the y-direction.

<a id="term-SHAPE-geometry-mask"></a>

SHAPE[‘geometry’][‘mask’]
: (*list*) The masks for this shape

<a id="term-SHAPE-geometry-mask_offset"></a>

SHAPE[‘geometry’][‘mask_offset’]
: (*list*) The mask offsets for this shape

<a id="term-SHAPE-geometry-position"></a>

SHAPE[‘geometry’][‘position’]
: (*list*) The x- and y-positions of the center point of the shape, constrained by the `SHAPE['geometry']['width']` and `SHAPE['geometry']['height']`.

<a id="term-SHAPE-geometry-shape_type"></a>

SHAPE[‘geometry’][‘shape_type’]
: (*str*) The shape type is either ‘planar’, ‘conformal’, ‘polygon’, or ‘ellipse’.

<a id="term-SHAPE-geometry-sidewall_angle"></a>

SHAPE[‘geometry’][‘sidewall_angle’]
: (*float*) [degrees] Angle of the side wall for a ‘planar’ shape relative to a vertical at 0 degrees.

<a id="term-SHAPE-geometry-tone"></a>

SHAPE[‘geometry’][‘tone’]
: (*str*) The tone of the mask (‘p’ or ‘n’)

<a id="term-SHAPE-geometry-vertices"></a>

SHAPE[‘geometry’][‘vertices’]
: (*list*) Pairs of [x,y] vertices that define the perimeter of a shape.

<a id="term-SHAPE-geometry-width"></a>

SHAPE[‘geometry’][‘width’]
: (*float*) Maximum size of the shape in the x-direction.

<a id="term-SHAPE-loss_dB_per_m"></a>

SHAPE[‘loss_dB_per_m’]
: (*float*) [dB/m] Absorption coefficient for power loss in the region defined by the shape.

<a id="term-SHAPE-mask"></a>

SHAPE[‘mask’]
: (*float* or *list*) Width of the a mask for etching a ‘planar’ shape. Also accepts a list to define both the width and the x-offset of the mask.

<a id="term-SHAPE-name"></a>

SHAPE[‘name’]
: (*str*) User-defined name of the shape. This name will be used to reference this shape in subsequent functions.

<a id="term-SHAPE-priority"></a>

SHAPE[‘priority’]
: (*float*) A value that defines the order in which the shape is drawn relative to other shapes. A higher value give a higher priority, putting the shape in front of other shapes with lower priority.

<a id="term-SHAPE-roughness_rms"></a>

SHAPE[‘roughness_rms’]
: (*list*) A list of two values describing the rms roughness on the vertical and horizontal edges of the shape.
  <br/>
  Alias: `st_dev_nm`

<a id="term-SHAPE-roughness_field_side"></a>

SHAPE[‘roughness_field_side’]
: (*str*) The side of each edge that [`scattering`](solver-analysis.md#scattering) reads the electric field from, ‘outside’ (the default) or ‘inside’ the shape.

<a id="term-SHAPE-metadata"></a>

SHAPE[‘metadata’]
: (*dict*) A dictionary of metadata associated with the shape

<a id="term-SHAPE-metadata-confinement"></a>

SHAPE[‘metadata’][‘confinement’]
: (*list*) Confinement factor for each mode in the corresponding shape.

<a id="term-SHAPE-metadata-edges"></a>

SHAPE[‘metadata’][‘edges’]
: (*list*) Definitions of edges for the corresponding shape where the scattering loss is calculated. These edges can be correlated to the loss values from `SHAPE['metadata']['scattering_all_edges']`.

<a id="term-SHAPE-metadata-scattering_all_edges"></a>

SHAPE[‘metadata’][‘scattering_all_edges’]
: (*list*) Calculated scattering loss for each edge of the shape, defined by `SHAPE['metadata']['edges']`.

<a id="term-SHAPE-metadata-scattering_horizontal_edges"></a>

SHAPE[‘metadata’][‘scattering_horizontal_edges’]
: (*list*) Calculated scattering loss for each horizontal edge of the shape.

<a id="term-SHAPE-metadata-scattering_sum"></a>

SHAPE[‘metadata’][‘scattering_sum’]
: (*list*) Total calculated scattering loss for all edges of the shape.

<a id="term-SHAPE-metadata-scattering_vertical_edges"></a>

SHAPE[‘metadata’][‘scattering_vertical_edges’]
: (*list*) Calculated scattering loss for each vertical edge of the shape.
