solprop.coupling.models#
The coupling models of SEP 31 section 4.3 and the scalar mode profiles they use.
CouplingModel selects one of three models and carries its approximation
budget:
same_basisExact coordinate recovery in a checked common reference: a copy for an identical basis, a declared invertible
BasisChange, or the flux-pairing recovery \(\mathbf a = F^{-1}\mathbf B\) of a general modal plane into a port of the same guide. Not an interface calculation, so it takes no budget.scalar_paraxialThe weighted least-squares fit \(G = S^\dagger M S\), \(\mathbf a = G^{-1}S^\dagger M\mathbf f\) of a scalar field onto scalar target profiles in the common paraxial measure \(M_0 = Y_0\,dA/2\), \(Y_0 = n_{\rm ref}\varepsilon_0c\), followed by the conversion to the target’s native true-power coefficients \(b = \sqrt{\operatorname{Re} n_{\rm eff}}\,a\).
vector_paraxialThe flux-pairing recovery \(\mathbf a = F^{-1}\mathbf B\) onto a general modal provider’s E/H at its nodes, with the incident H or the forward closure \(\mathbf H_t = Y_0\hat{\mathbf z}\times\mathbf E_t\).
ScalarModeBasis is the scalar transverse profile set the scalar model uses:
the capillary \(HE_{1m}\) family, \(J_0(u_m r/a)\) inside the core and zero
outside (SEP 31 section 4.4), and the weak-guidance \(LP_{0m}\) family of a
step-index fibre, \(J_0(Ur/a)\) inside and \(J_0(U)K_0(Wr/a)/K_0(W)\)
outside (Snyder and Love 1983, section 14-3; Gloge 1971). Each profile is normalised
to unit area integral of its square, and its order-zero Hankel transform is
evaluated in closed form, so an overlap can be taken in a plane’s own spectral
quadrature without sampling a profile’s kink.
The manual page is docs/guide/workflows/coupling.md.
Module Attributes
A coupling model of SEP 31 section 4.3. |
|
Every |
|
The scalar profile family of a |
Functions
|
Return the admitted cone half-angle \(\theta_*\) of a model budget. |
|
Return a composite Gauss--Legendre rule for |
Classes
|
A declared invertible change of modal basis or gauge for |
|
Select a coupling model of SEP 31 section 4.3 and its approximation budget. |
|
Scalar transverse profiles of an ordinary mode set, bound to a temporal grid. |
- class solprop.coupling.models.BasisChange(matrix, source, target)[source]#
Bases:
objectA declared invertible change of modal basis or gauge for
same_basis.The target coefficients are
matrix @ bper bin and polarisation. The change must preserve energy between the plane’s metric and the port’s,T^H Q_B T = Q_A, tosolprop.coupling.port.METRIC_TOLERANCErelative; it relabels the same physical field and is refused otherwise.- Attributes:
- matrixnumpy.ndarray
Optics-convention map from the plane’s columns to the port’s, shape
(n_modes_target, n_modes_source)or with a trailingn_omegaaxis for a frequency-dependent gauge, dimensionless.- sourcestr
The plane’s basis identity the change was declared for.
- targetstr
The port’s basis identity.
- Raises:
- CouplingError
If the matrix is not finite and two- or three-dimensional.
- at(n_omega)[source]#
Return the matrix at every bin, frequency axis first.
- Parameters:
- n_omegaint
The number of bins.
- Returns:
- numpy.ndarray
Shape
(n_omega, n_modes_target, n_modes_source).
- Raises:
- CouplingError
If a frequency-dependent matrix has another number of bins.
- matrix: Complex[ndarray, 'n_modes_target n_modes_source *n_omega']#
- class solprop.coupling.models.CouplingModel(kind, model_error=None, basis_change=None)[source]#
Bases:
objectSelect a coupling model of SEP 31 section 4.3 and its approximation budget.
- Attributes:
- kind{‘same_basis’, ‘scalar_paraxial’, ‘vector_paraxial’}
The model.
- model_errorfloat or None, optional
The dimensionless energy budget \(\epsilon_m\) in (0, 1) that the approximation’s defects, angular tails, closure, passivity excess and numerical errors together must fit; required by the two approximate models, refused by
same_basis, which approximates nothing. It is separate from numerical accuracy and is not a coupling-efficiency floor.- basis_changeBasisChange or None, optional
A declared invertible change of basis or gauge,
same_basisonly.
- Raises:
- CouplingError
If a budget is missing, outside (0, 1) or given to
same_basis, or a basis change is given to an approximate model.
Examples
>>> CouplingModel("scalar_paraxial", model_error=0.05) CouplingModel(kind='scalar_paraxial', model_error=0.05, basis_change=None)
- basis_change: BasisChange | None = None#
- property cone: float[source]#
Return the admitted cone half-angle of the budget.
- Returns:
- float
cone_angle()of model_error, rad.
- Raises:
- CouplingError
For
same_basis, which has no budget.
- solprop.coupling.models.MODEL_KINDS: tuple[Literal['same_basis', 'scalar_paraxial', 'vector_paraxial'], ...] = ('same_basis', 'scalar_paraxial', 'vector_paraxial')#
Every
ModelKind, in a fixed order.
- solprop.coupling.models.ModelKind#
A coupling model of SEP 31 section 4.3.
alias of
Literal[‘same_basis’, ‘scalar_paraxial’, ‘vector_paraxial’]
- solprop.coupling.models.ProfileFamily#
The scalar profile family of a
ScalarModeBasis.alias of
Literal[‘capillary’, ‘step_index’]
- class solprop.coupling.models.ScalarModeBasis(family, labels, radius, u, w, jones, effective_index, core_index=None, cladding_index=None, wall_term=None, identity='')[source]#
Bases:
objectScalar transverse profiles of an ordinary mode set, bound to a temporal grid.
Each channel is a profile \(v_m(r)\) normalised to \(\int|v_m|^2dA = 1\), times a real unit Jones vector. The guide’s own vacuum-normalised field per internal amplitude is \(\sqrt{2/(\varepsilon_0c)}\,v_m\), so a true-power coefficient \(b_m = \sqrt{\operatorname{Re}n_{{\rm eff},m}}a_m\) carries the field \(\sqrt{2/(\varepsilon_0c\operatorname{Re}n_{{\rm eff},m})}\,b_m v_m\) (
docs/dev/conventions.mdsection 4). The profiles are those of the run’s own basis: a capillary’s do not depend on frequency, and a step-index mode’s are frozen at its declared profile wavelength exactly as the run’s are.Build one with
from_modes().- Attributes:
- family{‘capillary’, ‘step_index’}
The profile family.
- labelstuple of str
Channel labels, in column order.
- radiusfloat
Core radius at the plane, m.
- unumpy.ndarray
Dimensionless core wavenumber of each profile, shape
(n_modes,): the J0 zero of a capillary HE1m mode, U of an LP0m mode.- wnumpy.ndarray
Dimensionless cladding decay W of each LP0m profile, shape
(n_modes,); zero for a capillary, whose profile vanishes outside the core.- jonesnumpy.ndarray
Real unit Jones vector
(x, y)of each channel, shape(n_modes, 2).- effective_indexnumpy.ndarray
\(\operatorname{Re}n_{\rm eff}\) of each channel at each bin, shape
(n_modes, n_omega); zero on bins outside the active positive band.- core_indexnumpy.ndarray or None, optional
Real core index at each bin, shape
(n_omega,): a capillary’s gas, a step-index fibre’s core; zero off the active positive band.- cladding_indexnumpy.ndarray or None, optional
Real cladding index at each bin of a step-index basis, shape
(n_omega,).- wall_termnumpy.ndarray or None, optional
\(|\nu_n|\) of a capillary’s HE modes at each bin, shape
(n_omega,): the Marcatili wall term \(\nu_n = (\varepsilon + 1)/(2\sqrt{\varepsilon - 1})\) of the wall permittivity \(\varepsilon\); zero off the active positive band. It sets the leaky field’s departure from the scalar profile (leaky()).- identitystr, optional
A short description of the source modes, for reports.
- Raises:
- CouplingError
If the arrays disagree in shape.
- cone_gram(kappa_star)[source]#
Return the Gram of the profiles’ angular content inside a cone.
\(\int_{|\boldsymbol\kappa|<\kappa_*}\tilde V_m\tilde V_n d^2\kappa/(2\pi)^2 = \int_0^{\kappa_*}\tilde v_m\tilde v_n\,2\pi\kappa\,d\kappa\), by composite Gauss–Legendre panels of at most half a period of \(J_0(\kappa a)\). The tail outside the cone is the whole-plane
gram()minus this.- Parameters:
- kappa_starfloat
The cone’s transverse wavenumber, rad/m.
- Returns:
- numpy.ndarray
Real symmetric, dimensionless, shape
(n_modes, n_modes).
- effective_index: Float[ndarray, 'n_modes n_omega']#
- classmethod from_modes(modes, grid, z=0.0)[source]#
Return the scalar profiles of an ordinary mode set at a plane.
Admitted are a capillary’s \(HE_{1m}\) modes (Marcatili; the scalar J0 profile is exactly their transverse field) and a step-index fibre’s \(HE_{1m}\) modes taken in the weak-guidance limit as \(LP_{0m}\). Every other family has angular structure the scalar model cannot hold and is refused by name.
- Parameters:
- modessequence of solprop.modes.protocol.Mode
The run’s modes, in column order.
- gridsolprop.grid.TimeGrid
The run’s temporal grid, on whose active positive bins the effective indices are evaluated.
- zfloat, optional
The plane’s position along the guide, m.
- Returns:
- ScalarModeBasis
The profiles.
- Raises:
- CouplingError
For an empty set, mixed or unsupported families, or modes of different radii.
- gram()[source]#
Return the exact whole-plane Gram of the normalised profiles.
Distinct profiles of one family are orthogonal (different zeros of the core’s eigenvalue equation); the same profile carried by two channels, the two polarisations of one mode, overlaps itself fully, and their Jones vectors make the channels orthogonal.
- Returns:
- numpy.ndarray
One where two profiles are the same and zero otherwise, shape
(n_modes, n_modes).
- hankel(kappa)[source]#
Return each normalised profile’s order-zero Hankel transform.
\(\tilde v_m(\kappa) = \int_0^\infty v_m(r)J_0(\kappa r)r\,dr\), the convention of
solprop.hankel, in closed form; the two-dimensional Fourier transform of the axisymmetric profile is \(2\pi\tilde v_m\).- Parameters:
- kappanumpy.ndarray
Transverse wavenumbers, rad/m, non-negative, shape
(n_k,).
- Returns:
- numpy.ndarray
In m, shape
(n_modes, n_k).
- jones: Float[ndarray, 'n_modes 2']#
- leaky(omega)[source]#
Return a capillary’s leaky-field parameter at each bin.
Marcatili’s leaky HE1m core field is \(J_0(u_m(1 - i\delta)r/a)\) with \(\delta = \nu_n c/(\omega a)\), where the scalar profile has \(\delta = 0\) (Marcatili and Schmeltzer 1964, doi:10.1002/j.1538-7305.1964.tb04108.x). Its energy-weighted mean over a coupling’s occupied bins is the range parameter of
CAPILLARY_ENVELOPE.- Parameters:
- omeganumpy.ndarray
Absolute angular frequency of each bin, rad/s, shape
(n_omega,).
- Returns:
- numpy.ndarray or None
\(|\nu_n|c/(\omega a)\), dimensionless, shape
(n_omega,), zero off the active positive band; None for a basis without a wall term (a step-index one).
- outer()[source]#
Return the radius beyond which every profile is negligible, m.
- Returns:
- float
The core radius for a capillary; for an LP set, where the slowest cladding tail has decayed by 39 e-foldings,
log(1e17).
- u: Float[ndarray, 'n_modes']#
- values(r)[source]#
Return each normalised profile at radii.
- Parameters:
- rnumpy.ndarray
Non-negative radii, m, shape
(n_r,).
- Returns:
- numpy.ndarray
\(v_m(r)\) in 1/m, shape
(n_modes, n_r).
- w: Float[ndarray, 'n_modes']#
- solprop.coupling.models.cone_angle(model_error)[source]#
Return the admitted cone half-angle \(\theta_*\) of a model budget.
SEP 31 sections 4.3 and 4.6: \(1 - \cos\theta_* = \epsilon_m/8\).
- Parameters:
- model_errorfloat
The budget \(\epsilon_m\), in (0, 1).
- Returns:
- float
\(\theta_*\) in rad.
Examples
>>> f"{cone_angle(0.08):.6f}" '0.141539'
- solprop.coupling.models.radial_rule(breaks, outer, *, panel)[source]#
Return a composite Gauss–Legendre rule for
int f(r) 2 pi r dr.Panels break at each of breaks (a profile’s derivative jumps there) and are at most panel long, so each holds a smooth piece of the integrand.
- Parameters:
- breakssequence of float
Interior radii where the integrand is not smooth, m.
- outerfloat
The rule’s outer radius, m.
- panelfloat
Largest panel length, m.
- Returns:
- tuple of numpy.ndarray
Nodes in m and area weights in m^2 (the Jacobian
2 pi rincluded), each shape(n_r,).
Examples
>>> import numpy as np >>> r, w = radial_rule([1.0], 2.0, panel=0.5) >>> f"{np.sum(w):.12f}" # the area of the disc of radius 2 '12.566370614359'