Result
The Result object returned by a Maxwell simulation, with field, material, monitor, port, plotting, and save/load access.
mw.Simulation.fdtd(...).run() and mw.Simulation.fdfd(...).run() return a Result (witwin.maxwell.Result, usually mw.Result). This page covers everything you reach from it: field and material tensors, frequency selection, monitor payloads, ports and circuits, typed post-processing helpers, plotting, and persistence. All tensors are torch.Tensor objects that stay on the scene device and keep any autograd graph, unless the text says otherwise.
result = mw.Simulation.fdtd(scene, frequencies=[0.9e9, 1.1e9], run_time=mw.TimeConfig(time_steps=400)).run()
ex_all = result.E.x # shape [F, ...] for several frequencies
ex = result.at(frequency=1.1e9).E.x # one frequency
probe = result.monitor("probe")
result.save("run.pt")Result#
class Result(*, method, scene, prepared_scene=None, frequency=None, frequencies=None, solver=None, fields=None, monitors=None, ports=None, circuits=None, network=None, embedded_networks=None, array_run_data=None, metadata=None, solver_stats=None, raw_output=None, breakdown=None)Container for one simulation run. You normally get it from Simulation.run() or Result.load(...) and do not construct it yourself. All constructor arguments are keyword-only.
Run type, for example 'fdtd', 'fdfd', 'electrostatic', or 'capacitance'.
The declarative scene of the run. See Scene.
NoneCompiled scene. When None, it is built from scene on first use.
NoneSingle frequency in Hz. Used only when frequencies is None.
NoneFrequencies in Hz. You must give frequency or a non-empty frequencies.
NoneSolver instance that produced the run. Needed by plot.field and some post-processing.
NoneFull-domain field tensors keyed by upper-case component name ('EX', 'EY', 'EZ').
NoneMonitor payloads keyed by monitor name. A WireData value must be stored under its own monitor_name.
NonePort records. Each key must equal the record's port_name.
NoneCircuit records. Each key must equal the record's circuit_name.
NoneNetwork (S-parameter) data, or None.
NoneEmbedded network records. Each key must equal the record's name.
NoneRetained array sweep data, used by array_basis.
NoneRun metadata.
NoneSolver statistics, merged into stats().
NoneRaw solver output.
NoneDielectric-breakdown output, exposed as breakdown_data.
Raises ValueError when no frequency is given or a mapping key does not match its record name; TypeError when a mapping value has the wrong type.
Plain attributes:
| Attribute | Content |
|---|---|
method | run type string |
scene | declarative scene |
frequencies | tuple of frequencies in Hz |
frequency | first entry of frequencies |
solver | solver instance, or None (for example after load) |
raw_output | raw solver output |
Note
The standard FDTD and FDFD run paths store only the electric field components EX, EY, EZ as full-domain fields. Record magnetic fields with a monitor; see Monitors. A single-frequency FDTD run with full_field_dft=False stores the electric field at the last time step instead of a frequency-domain phasor; pass full_field_dft=True to Simulation.fdtd(...) for phasors. See Simulation.
Each component lives on its own Yee-staggered grid, so component shapes differ. With several frequencies, each field tensor has a leading frequency axis of length F.
Result.E#
Result.E -> ResultFieldAccessorProperty. Electric field accessor for all frequencies: result.E.x, result.E.y, result.E.z. Same as result.at().E.
Result.H#
Result.H -> ResultFieldAccessorProperty. Magnetic field accessor. Accessing a component raises KeyError when the result holds no H fields, which is the case for FDTD and FDFD runs.
Result.materials#
Result.materials -> ResultMaterialsAccessorProperty. Material accessor: result.materials.eps.scalar, result.materials.mu.x, and so on. Same as result.at().materials.
Result.at#
Result.at(*, frequency=None, freq_index=None, expand_symmetry=False, resolve_modal=True) -> ResultSelectionReturns a view of the result fixed to one frequency and options. Result.select is an alias.
NoneFrequency in Hz to select. It must match a result frequency (relative tolerance 1e-9).
NoneIndex into frequencies. Do not combine with frequency.
FalseMirror fields and materials across symmetry planes back to the full domain.
TrueDefault for monitor(...) on the view: resolve mode, diffraction, and emission monitors to their higher-level dicts.
Raises ValueError when both frequency and freq_index are given. An unknown frequency raises KeyError, and an out-of-range index raises IndexError, when you read data from the view.
view = result.at(frequency=1.1e9)
ex = view.E.x
center = view.monitor("center")["data"]Result.fields#
Result.fields -> dict[str, torch.Tensor]Property. A copy of the field dict, keyed by upper-case component name.
Result.monitors#
Result.monitors -> dict[str, Any]Property. A copy of the raw monitor dict as recorded, without frequency selection, cropping, or modal resolution.
Result.field#
Result.field(name='E', *, expand_symmetry=False, frequency=None, freq_index=None)Returns field data by name.
'E''E' or 'H' (case-insensitive) returns a dict of the available components, for example {'EX': ..., 'EY': ..., 'EZ': ...}. A component name such as 'Ex' returns that tensor.
FalseMirror across symmetry planes to the full domain.
NoneFrequency in Hz to select.
NoneFrequency index to select.
Returns dict[str, torch.Tensor] for 'E'/'H', otherwise torch.Tensor.
Result.tensor#
Result.tensor(name, *, expand_symmetry=False, frequency=None, freq_index=None) -> torch.TensorReturns one field component tensor.
Component name, for example 'Ex' (case-insensitive).
FalseMirror across symmetry planes to the full domain. Components normal or tangential to a PEC/PMC plane get the matching sign.
NoneFrequency in Hz to select.
NoneFrequency index to select.
Without a selection, a multi-frequency result returns the full tensor with its leading frequency axis.
Raises KeyError when the component is not stored; KeyError or IndexError for an unknown frequency or index.
Result.material#
Result.material(name='eps_r', *, expand_symmetry=False) -> torch.TensorReturns a relative material tensor of the compiled scene.
'eps_r'Material quantity (case-insensitive), see the table below.
FalseMirror across symmetry planes to the full domain.
| Quantity | Accepted names |
|---|---|
| Relative permittivity | eps, eps_r, permittivity |
| Permittivity components | eps_x, epsilon_x, permittivity_x (and y, z) |
| Relative permeability | mu, mu_r, permeability |
| Permeability components | mu_x, permeability_x (and y, z) |
Raises KeyError for another name.
Result.monitor#
Result.monitor(name, *, frequency=None, freq_index=None, resolve_modal=True)Returns the processed data of a named monitor. The return type depends on the monitor class; see the table in Monitors.
Monitor name. For one face of a closed surface, use '<surface>::<label>'.
NoneSelect one monitor frequency in Hz. The returned dict then has frequencies of length 1 and data without the frequency axis.
NoneSelect a monitor frequency by index into the monitor's own frequencies.
TrueResolve ModeMonitor, DiffractionMonitor, and DipoleEmissionMonitor payloads into modal, diffraction-order, and emission dicts. With False, you get the raw plane or point dict.
The lookup works in this order:
Typed records
A
WireMonitorreturns itsWireData. APowerLossMonitorreturnspower_loss(name). Both raiseValueErrorif you passfrequencyorfreq_index.Raw payload
Everything else goes through
raw_monitor(name, ...): closed surfaces are assembled from their faces, material monitors are evaluated from the compiled materials, and finite planes are cropped.Resolution
With
resolve_modal=True, diffraction, dipole-emission, and mode payloads are converted to their higher-level dicts. Closed-surface and other payloads are returned as they are.
Raises KeyError when the monitor has no recorded data, for example a ComponentStressMonitor (use component_stress). Use breakdown(name) for a BreakdownMonitor.
flux = result.monitor("transmission")["flux"]
modal = result.monitor("port_mode", frequency=3e14)
plane = result.monitor("port_mode", resolve_modal=False)Result.raw_monitor#
Result.raw_monitor(name, *, frequency=None, freq_index=None)Returns the underlying point or plane dict of a monitor, with frequency selection and finite-plane cropping applied but no modal, diffraction, or emission resolution. Closed surfaces and material monitors are built the same way as in monitor. A WireData record is returned as is.
Monitor name.
NoneMonitor frequency in Hz to select.
NoneMonitor frequency index to select.
Raises KeyError when no data is stored under name; ValueError when you select a frequency on WireData.
Result.port#
Result.port(name) -> PortDataReturns the record of a lumped or terminal port. Raises KeyError listing the available names. See Ports.
Result.ports#
Result.ports -> dict[str, PortData]Property. A copy of all port records.
Result.circuit#
Result.circuit(name) -> CircuitDataReturns the record of a coupled circuit. Raises KeyError listing the available names. See Circuits.
Result.circuits#
Result.circuits -> dict[str, CircuitData]Property. A copy of all circuit records.
Result.network#
Result.network -> NetworkData | NoneProperty. Network (S-parameter) data, or None. See Networks.
Result.embedded_network#
Result.embedded_network(name) -> EmbeddedNetworkDataReturns one embedded network record. Raises KeyError listing the available names.
Result.embedded_networks#
Result.embedded_networks -> dict[str, EmbeddedNetworkData]Property. A copy of all embedded network records.
Result.antenna#
Result.antenna(*, surface, driven_port, polarization=None, theta=None, phi=None, theta_points=181, phi_points=361, radius=1.0, phase_center=None, frame=None, batch_size=1024) -> AntennaDataComputes far-field antenna data from a ClosedSurfaceMonitor and a driven port. surface is the closed-surface monitor name; driven_port is a port name or PortData. See Antennas and arrays for the parameters and AntennaData.
Result.array_basis#
Result.array_basis(*, monitor, polarization=None, theta=None, phi=None, theta_points=181, phi_points=361, radius=1.0, phase_center=None, frame=None, batch_size=1024) -> ArrayBasisDataBuilds a reusable embedded-pattern basis from a port sweep run. See Antennas and arrays.
Result.power_loss#
Result.power_loss(name, *, electric_fields=None, volume_channels=None, integrated_channels=None, surface_channels=None, face_areas=None, line_channels=None, line_lengths=None, occupancy=None, material_ids=None, geometry_ids=None) -> PowerLossDataComputes the loss channels of a declared PowerLossMonitor. The conduction channel is computed from the stored Ex, Ey, Ez unless you pass electric_fields; the other arguments supply explicit channel data. See Safety.
Raises KeyError when name is not a PowerLossMonitor; NotImplementedError for a non-FDTD result; RuntimeError when conduction needs fields that the run did not store (run FDTD with full_field_dft=True).
Result.incident_power_density#
Result.incident_power_density(monitor, *, spatial_average=<unset>) -> IncidentPowerDensityReduces an IncidentPowerDensityMonitor to incident power density in W/m^2 and plane flux in W. Leave spatial_average unset to use the monitor's window area, pass None to disable averaging, or pass an area in m^2 to override it. Raises KeyError when monitor is not an IncidentPowerDensityMonitor. See Safety.
Result.sar#
Result.sar(monitor, *, averaging=None, normalization=None, electric_fields=None, volume_channels=None) -> SARResultReduces a PowerLossMonitor and the tissue mass model to SAR. It never runs a solver. averaging is a SARAveraging; normalization defaults to PowerNormalization.none() (unit source amplitude). Raises KeyError for a monitor that is not a PowerLossMonitor and NotImplementedError for a non-FDTD result. See Safety.
Result.breakdown#
Result.breakdown(name) -> BreakdownStressDataReturns the dielectric-stress record of a BreakdownMonitor: peak field, exceedance durations, qualifying locations, and per-cell maps kept on the device. Raises KeyError listing the available names. See Safety.
Result.breakdown_names#
Result.breakdown_names() -> tuple[str, ...]Names of the BreakdownMonitor records in the result.
Result.breakdown_data#
Result.breakdown_data -> BreakdownResultData | NoneProperty. Output of dielectric-breakdown materials, or None when the scene has none. This is separate from breakdown(name), which reads a BreakdownMonitor.
Result.breakdown_events#
Result.breakdown_events -> tupleProperty. Breakdown events ordered by (step, cell_index), or an empty tuple when breakdown is inactive.
Result.component_stress#
Result.component_stress(name) -> ComponentStressDataReduces the voltage and current series bound by a ComponentStressMonitor to power P = V I, cumulative energy, and an exceedance summary against its ComponentRating. Raises KeyError when the binding or a series is missing, and ValueError when the two series have different sample counts or time axes. See Safety.
Result.component_stress_names#
Result.component_stress_names() -> tuple[str, ...]Names of the ComponentStressMonitor bindings on the scene.
Result.esd_waveform#
Result.esd_waveform(name) -> ESDPortRecordReturns the injection record of an ESDCurrentSource: target waveform diagnostics, the waveform resampled onto the run time grid, provenance, and measured (the port's PortData when the run recorded one, otherwise None). Raises KeyError listing the available sources. See Safety.
Result.esd_waveform_names#
Result.esd_waveform_names() -> tuple[str, ...]Names of the ESDCurrentSource sources on the scene.
Result.esd_generator#
Result.esd_generator(name) -> dict[str, Any]Returns the provenance dict of a circuit-driven ESD generator network (built by ESDVoltageSource.build_circuit). The port voltage and current time series live on result.circuit(name). Raises KeyError listing the available names.
Result.esd_generator_names#
Result.esd_generator_names() -> tuple[str, ...]Names of the ESD generator circuits on the scene.
Result.electrostatic#
Result.electrostatic -> ElectrostaticResultDataProperty. Output of a Simulation.electrostatic(...) run. Raises AttributeError for other runs. See Electrostatics.
Result.electrostatic_prebias#
Result.electrostatic_prebias -> dict | NoneProperty. Provenance of the electrostatic pre-bias initial condition of an FDTD run, or None.
Result.capacitance#
Result.capacitance -> CapacitanceDataProperty. Output of a Simulation.capacitance(...) run. Raises AttributeError for other runs.
Result.prepared_scene#
Result.prepared_sceneProperty. The compiled scene. It is built from scene on first access when the result has none (for example after load without prepared_scene).
Result.solver_stats#
Result.solver_stats -> dict[str, Any]Property. A copy of the raw solver statistics.
Result.stats#
Result.stats() -> dict[str, Any]Returns solver_stats plus method, frequency, frequencies, num_frequencies, num_fields, num_monitors, num_ports, num_circuits, has_network, and num_embedded_networks. FDTD runs include keys such as time_steps, steps_run, dt, elapsed_s, ms_per_step, steps_per_second, dft_window, full_field_dft, and shutoff_triggered. FDFD runs include solver, converged, solver_info, and final_residual.
stats = result.stats()
print(stats["time_steps"], stats["ms_per_step"])Result.plot#
Result.plot -> ResultPlotterProperty. Plotting helper; see ResultPlotter. A new helper is created on each access.
Result.save#
Result.save(path) -> NoneSaves a detached CPU snapshot with torch.save. It stores method, frequencies, fields, monitors, ports, circuits, network, embedded networks, metadata, and solver statistics. It does not store the scene, prepared scene, solver, raw output, autograd graphs, retained array sweep columns, or breakdown_data. Parent directories are created.
Output file path.
Tip
To reuse array embedded patterns later, call result.array_basis(...) and save the returned ArrayBasisData before you save the result.
Result.load#
Result.load(path, *, scene, prepared_scene=None, map_location='cpu') -> ResultClassmethod. Loads a snapshot written by save. You supply the scene, because it is not saved.
Snapshot file path.
Keyword-only. The declarative scene of the saved run.
NoneKeyword-only. Compiled scene, if you have one.
'cpu'Keyword-only. Passed to torch.load.
Raises ValueError when the file is not a schema-version-2 result snapshot or misses required keys.
Warning
Result files use pickle-backed torch.load(weights_only=False). Load them only from trusted sources.
result.save("run.pt")
restored = mw.Result.load("run.pt", scene=scene)
data = restored.monitor("state")Result.save_sharded#
Result.save_sharded(directory)Writes the result metadata and each field shard to a new directory without assembling global field tensors. It needs a solver that provides export_field_shards() (a multi-GPU run). See Batch and multi-GPU.
Raises FileExistsError when directory exists; RuntimeError when the solver cannot export shards.
Result.load_sharded#
Result.load_sharded(directory, *, scene, prepared_scene=None, gather_fields=False, map_location='cpu') -> ResultClassmethod. Loads a directory written by save_sharded. Fields are gathered only when gather_fields=True. Raises TypeError when gather_fields is not a bool.
Result.is_sharded#
Result.is_sharded -> boolProperty. True for a result loaded with load_sharded. The related properties sharded_manifest and shard_paths (a tuple of Path) describe the loaded shards.
ResultSelection#
class ResultSelection(result, frequency=None, freq_index=None, expand_symmetry=False, resolve_modal=True)Frozen view returned by Result.at(...). Every accessor passes the stored frequency and options to the Result methods. You get it from result.at(...); it is not exported at package level.
Raises ValueError when both frequency and freq_index are set.
ResultSelection.E#
ResultSelection.E -> ResultFieldAccessorProperty. Electric field accessor for the selected frequency.
ResultSelection.H#
ResultSelection.H -> ResultFieldAccessorProperty. Magnetic field accessor for the selected frequency.
ResultSelection.materials#
ResultSelection.materials -> ResultMaterialsAccessorProperty. Material accessor. Materials honour expand_symmetry and ignore the frequency.
ResultSelection.field#
ResultSelection.field(name='E')Same as Result.field with the view's frequency and expand_symmetry.
ResultSelection.tensor#
ResultSelection.tensor(name) -> torch.TensorSame as Result.tensor with the view's frequency and expand_symmetry.
ResultSelection.material#
ResultSelection.material(name='eps_r') -> torch.TensorSame as Result.material with the view's expand_symmetry.
ResultSelection.monitor#
ResultSelection.monitor(name, *, resolve_modal=None)Same as Result.monitor with the view's frequency. resolve_modal=None uses the view's setting.
ResultSelection.raw_monitor#
ResultSelection.raw_monitor(name)Same as Result.raw_monitor with the view's frequency.
ResultSelection.at#
ResultSelection.at(*, frequency=<unset>, freq_index=<unset>, expand_symmetry=<unset>, resolve_modal=<unset>) -> ResultSelectionReturns a new view. Arguments you leave out keep the current view's values. ResultSelection.select is an alias.
full = result.at(freq_index=0, expand_symmetry=True)
ez = full.E.zResultFieldAccessor#
class ResultFieldAccessor(selection, family)Field accessor returned by E and H. family is 'E' or 'H'.
ResultFieldAccessor.x#
ResultFieldAccessor.x -> torch.TensorProperty. The x component (Ex or Hx) for the selection. The properties y and z return the other components. Each raises KeyError when the component is not stored.
ResultFieldAccessor.as_dict#
ResultFieldAccessor.as_dict() -> dict[str, torch.Tensor]Returns the stored components as a dict keyed 'x', 'y', 'z'. Missing components are skipped.
ResultMaterialsAccessor#
class ResultMaterialsAccessor(selection)Material accessor returned by materials.
ResultMaterialsAccessor.eps#
ResultMaterialsAccessor.eps -> ResultMaterialTensorAccessorProperty. Relative permittivity accessor. permittivity is an alias.
ResultMaterialsAccessor.mu#
ResultMaterialsAccessor.mu -> ResultMaterialTensorAccessorProperty. Relative permeability accessor. permeability is an alias.
ResultMaterialTensorAccessor#
class ResultMaterialTensorAccessor(selection, family)Accessor for one material quantity; family is 'eps' or 'mu'.
ResultMaterialTensorAccessor.scalar#
ResultMaterialTensorAccessor.scalar -> torch.TensorProperty. The scalar relative permittivity (eps_r) or permeability (mu_r). r is an alias.
ResultMaterialTensorAccessor.x#
ResultMaterialTensorAccessor.x -> torch.TensorProperty. The x component tensor. The properties y and z return the other components.
ResultMaterialTensorAccessor.as_dict#
ResultMaterialTensorAccessor.as_dict() -> dict[str, torch.Tensor]Returns a dict with keys 'scalar', 'x', 'y', 'z'.
eps = result.materials.eps.scalar
mu_z = result.materials.mu.zResultPlotter#
class ResultPlotter(result)Matplotlib plotting helper returned by result.plot.
ResultPlotter.field#
ResultPlotter.field(axis='z', position=0.0, component='abs', **kwargs) -> NonePlots a field-magnitude cross-section next to the permittivity on the same slice, by calling the solver's plot_cross_section. The slice is taken at the grid index nearest position.
'z'Slice normal: 'x', 'y', or 'z'.
0.0Slice coordinate in metres.
'abs''abs' plots the total magnitude of E, interpolated to cell centres; 'Ex', 'Ey', 'Ez' (case-insensitive) plot one component magnitude. Other values fall back to 'abs' for FDTD and raise ValueError for FDFD.
FalseKeyword argument passed to the solver. Plot in dB relative to the slice maximum.
(12, 5)Keyword argument passed to the solver. Figure size in inches.
NoneKeyword argument passed to the solver. Save the figure to this path and close it, instead of calling plt.show().
TrueKeyword argument passed to the solver. Print the saved path. The FDFD solver defaults to None, which uses the solver's own verbosity.
Returns None.
Raises RuntimeError when the result has no solver with plot_cross_section, for example after Result.load.
result.plot.field(axis="z", position=0.0, component="abs", save_path="field_z0.png")ResultPlotter.material#
ResultPlotter.material(name='eps_r', axis='z', position=0.0, figsize=(8, 6), cmap='viridis')Plots a slice of a material tensor from Result.material(name).
'eps_r'Material name, as accepted by Result.material.
'z'Slice normal.
0.0Slice coordinate in metres; the nearest grid index is used.
(8, 6)Figure size in inches.
'viridis'Matplotlib colormap name.
Returns (fig, ax), the Matplotlib figure and axes. The figure is not shown or saved; call fig.savefig(...) or plt.show() yourself.
fig, ax = result.plot.material("eps_r", axis="y", position=0.0)
fig.savefig("eps_y0.png")