photonforge 1.3.1__cp310-cp310-win_amd64.whl → 1.3.2__cp310-cp310-win_amd64.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.
Files changed (39) hide show
  1. photonforge/__init__.py +17 -12
  2. photonforge/_backend/default_project.py +398 -22
  3. photonforge/circuit_base.py +5 -40
  4. photonforge/extension.cp310-win_amd64.pyd +0 -0
  5. photonforge/live_viewer.py +2 -2
  6. photonforge/{analytic_models.py → models/analytic.py} +47 -23
  7. photonforge/models/circuit.py +684 -0
  8. photonforge/{data_model.py → models/data.py} +4 -4
  9. photonforge/{tidy3d_model.py → models/tidy3d.py} +772 -10
  10. photonforge/parametric.py +60 -28
  11. photonforge/plotting.py +1 -1
  12. photonforge/pretty.py +1 -1
  13. photonforge/thumbnails/electrical_absolute.svg +8 -0
  14. photonforge/thumbnails/electrical_adder.svg +9 -0
  15. photonforge/thumbnails/electrical_amplifier.svg +5 -0
  16. photonforge/thumbnails/electrical_differential.svg +6 -0
  17. photonforge/thumbnails/electrical_integral.svg +8 -0
  18. photonforge/thumbnails/electrical_multiplier.svg +9 -0
  19. photonforge/thumbnails/filter.svg +8 -0
  20. photonforge/thumbnails/optical_amplifier.svg +5 -0
  21. photonforge/thumbnails.py +10 -38
  22. photonforge/time_steppers/amplifier.py +353 -0
  23. photonforge/{analytic_time_steppers.py → time_steppers/analytic.py} +191 -2
  24. photonforge/{circuit_time_stepper.py → time_steppers/circuit.py} +6 -5
  25. photonforge/time_steppers/filter.py +400 -0
  26. photonforge/time_steppers/math.py +331 -0
  27. photonforge/{modulator_time_steppers.py → time_steppers/modulator.py} +9 -20
  28. photonforge/{s_matrix_time_stepper.py → time_steppers/s_matrix.py} +3 -3
  29. photonforge/{sink_time_steppers.py → time_steppers/sink.py} +6 -8
  30. photonforge/{source_time_steppers.py → time_steppers/source.py} +20 -18
  31. photonforge/typing.py +5 -0
  32. photonforge/utils.py +89 -15
  33. {photonforge-1.3.1.dist-info → photonforge-1.3.2.dist-info}/METADATA +2 -2
  34. {photonforge-1.3.1.dist-info → photonforge-1.3.2.dist-info}/RECORD +37 -27
  35. photonforge/circuit_model.py +0 -335
  36. photonforge/eme_model.py +0 -816
  37. {photonforge-1.3.1.dist-info → photonforge-1.3.2.dist-info}/WHEEL +0 -0
  38. {photonforge-1.3.1.dist-info → photonforge-1.3.2.dist-info}/entry_points.txt +0 -0
  39. {photonforge-1.3.1.dist-info → photonforge-1.3.2.dist-info}/licenses/LICENSE +0 -0
@@ -9,9 +9,9 @@ from typing import Any, Literal
9
9
 
10
10
  import numpy
11
11
 
12
- from . import typing as pft
13
- from .cache import cache_s_matrix
14
- from .extension import (
12
+ from .. import typing as pft
13
+ from ..cache import cache_s_matrix
14
+ from ..extension import (
15
15
  Component,
16
16
  Interpolator,
17
17
  Model,
@@ -28,8 +28,8 @@ from .extension import (
28
28
  register_model_class,
29
29
  text,
30
30
  )
31
- from .tidy3d_model import _ModeSolverRunner
32
- from .utils import C_0, route_length
31
+ from ..utils import C_0, _angles_equal, _gather_status, route_length
32
+ from .tidy3d import _align_and_overlap, _ModeSolverRunner
33
33
 
34
34
  _ComplexCoeff = pft.array(complex, 0, 2)
35
35
  _ComplexCoeff1D = pft.array(complex, 0, 1)
@@ -1693,27 +1693,33 @@ def _port_with_x_section(port_name, component):
1693
1693
 
1694
1694
 
1695
1695
  class _WaveguideModelRunner:
1696
- def __init__(self, runner, free_space_phase, frequencies, ports) -> None:
1697
- self.runner = runner
1696
+ def __init__(self, runners, free_space_phase, frequencies, ports, overlap_mag_warning) -> None:
1697
+ self.runners = runners
1698
1698
  self.free_space_phase = free_space_phase
1699
1699
  self.frequencies = frequencies
1700
1700
  self.ports = ports
1701
+ self.overlap_mag_warning = overlap_mag_warning
1701
1702
  self._s_matrix = None
1702
1703
 
1703
1704
  @property
1704
1705
  def status(self):
1705
- return self.runner.status
1706
+ return _gather_status(*self.runners)
1706
1707
 
1707
1708
  @property
1708
1709
  def s_matrix(self):
1709
1710
  if self._s_matrix is None:
1710
- data = self.runner.data
1711
+ data = self.runners[0].data
1711
1712
  num_modes = next(iter(self.ports.values())).num_modes
1713
+ overlap = (
1714
+ _align_and_overlap(data, self.runners[1].data, self.overlap_mag_warning)[0]
1715
+ if len(self.runners) > 1
1716
+ else numpy.ones(num_modes)
1717
+ )
1712
1718
  n_complex = data.n_complex.values.T
1713
1719
  s = numpy.exp(1j * self.free_space_phase * n_complex)
1714
1720
 
1715
1721
  elements = {
1716
- (f"{port_in}@{mode}", f"{port_out}@{mode}"): s[mode]
1722
+ (f"{port_in}@{mode}", f"{port_out}@{mode}"): s[mode] * overlap[mode]
1717
1723
  for port_in in self.ports
1718
1724
  for port_out in self.ports
1719
1725
  for mode in range(num_modes)
@@ -1936,20 +1942,38 @@ class WaveguideModel(Model):
1936
1942
  port.spec.added_solver_modes = 0
1937
1943
 
1938
1944
  if n_type is str:
1939
- ms_port = _port_with_x_section(port_names[0], component)
1945
+ ms_ports = (
1946
+ _port_with_x_section(port_names[0], component),
1947
+ _port_with_x_section(port_names[1], component),
1948
+ )
1940
1949
  else:
1941
- ms_port = port0.copy(True)
1950
+ ms_ports = (port0.copy(True), port1.copy(True))
1942
1951
  if n_type is PortSpec:
1943
- ms_port.spec = libcopy.deepcopy(self.n_complex)
1944
- runner = _ModeSolverRunner(
1945
- ms_port,
1946
- frequencies,
1947
- self.mesh_refinement,
1948
- component.technology,
1949
- cost_estimation=cost_estimation,
1950
- verbose=verbose,
1952
+ ms_ports[0].spec = libcopy.deepcopy(self.n_complex)
1953
+ ms_ports[1].spec = libcopy.deepcopy(self.n_complex)
1954
+
1955
+ rotation_fraction = (ms_ports[0].input_direction - ms_ports[1].input_direction) % 90
1956
+ is_multiple_of_90 = rotation_fraction < 1e-12 or (90 - rotation_fraction < 1e-12)
1957
+
1958
+ ms_ports[1].input_direction += 180
1959
+ if _angles_equal(ms_ports[1].input_direction, ms_ports[0].input_direction):
1960
+ # No need for mode overlap calculation
1961
+ ms_ports = ms_ports[:1]
1962
+
1963
+ runners = [
1964
+ _ModeSolverRunner(
1965
+ ms_port,
1966
+ frequencies,
1967
+ self.mesh_refinement,
1968
+ component.technology,
1969
+ cost_estimation=cost_estimation,
1970
+ verbose=verbose,
1971
+ )
1972
+ for ms_port in ms_ports
1973
+ ]
1974
+ return _WaveguideModelRunner(
1975
+ runners, free_space_phase, frequencies, component_ports, is_multiple_of_90
1951
1976
  )
1952
- return _WaveguideModelRunner(runner, free_space_phase, frequencies, component_ports)
1953
1977
 
1954
1978
  # Deprecated: kept for backwards compatibility with old phf files
1955
1979
  @classmethod
@@ -2057,11 +2081,11 @@ def _waveguide_transmission(
2057
2081
  dw = 2 * numpy.pi * (frequencies - reference_frequency)
2058
2082
  beta = beta0 + dw * (beta1 + dw * (beta2 / 2 + dw * beta3 / 6))
2059
2083
 
2060
- if v_piL is None:
2084
+ if v_piL is None or v_piL == 0.0:
2061
2085
  beta_eo = 0.0
2062
2086
  else:
2063
2087
  beta_eo = numpy.pi * voltage / v_piL
2064
- t = 10 ** (total_loss / -20) * numpy.exp(1j * (beta + beta_eo) * length)
2088
+ t = 10.0 ** (total_loss / -20.0) * numpy.exp(1j * (beta + beta_eo) * length)
2065
2089
  return t
2066
2090
 
2067
2091