solprop.modes.graded_index#
Solve radial TE/TM Maxwell sectors and a separately labelled LP approximation.
The symmetric variational problem uses continuous linear elements on a declared radial domain matched to an exact decaying exterior. Hybrid HE/EH sectors are refused: TE/TM evidence cannot qualify hybrid GRIN. The exterior material is explicit and the truncation radius is refined independently of the radial mesh.
Module Attributes
Largest share of a channel's power admitted beyond the matching radius. |
Classes
|
Solve bound radial vector sectors on an explicitly refined finite domain. |
|
Describe a finite radial power-law permittivity profile. |
|
Evaluate a radial material law independently of a longitudinal path. |
- class solprop.modes.graded_index.GradedIndexProvider(*, permittivity, exterior, radius, family, count, elements, extent, azimuthal_order=0, core_responses=())[source]#
Bases:
DisplayedSolve bound radial vector sectors on an explicitly refined finite domain.
A channel too close to cutoff for the declared finite domain is refused by name: more than
MAX_EXTERIOR_TAIL_FRACTIONof its power beyond the matching radius means the exact exterior continuation, not the discretised core, carries the mode. A returnedModalSampleis therefore always fully valid –validis allTrue– because an unsupported channel is refused rather than masked.- Attributes:
- permittivityRadialPermittivity
Core law without a z argument, evaluated at the local radial fraction.
- exteriorPermittivityLaw
Homogeneous exterior material law, independently declared.
- radiusfloat or ZProfile
Positive core radius in m; all z dependence follows this named path.
- family{‘TE’, ‘TM’, ‘LP’, ‘HE’, ‘EH’}
TE0/TM0 Maxwell sector or explicitly weak-guidance scalar LP approximation. Only
TE,TMandLPare supported.HEandEHstay in the type so that construction reaches the refusal and can be tested there; passing either raises rather than silently solving a hybrid sector.- countint
Number of consecutive radial channels, at least one.
- elementsint
At least eight radial elements per core radius; must be refined.
- extentfloat
Dimensionless matching radius, greater than one; exact Bessel exterior.
- azimuthal_orderint
Zero for TE/TM; non-negative scalar angular order for LP.
- core_responsestuple
The core region’s own declared physical responses, at most one of each kind, exactly as
solprop.modes.material.MaterialRegiontakes them. Empty, the default, declares a linear guide: its nodes carry no polarisation, which is what a linear self-imaging reference wants. The exterior is always linear, because the radial sectors this provider solves are bound and their exterior is the exact Bessel continuation – what little field is there is the tailMAX_EXTERIOR_TAIL_FRACTIONalready bounds, and a response declared on it would be evaluated at nodes the rule barely resolves.
- at_parameters(values)[source]#
Freeze the declared radius path at explicit parameter values.
- Parameters:
- valuescollections.abc.Mapping
Any subset of core_radius, in m and strictly positive. A name left out keeps its path; a name this provider does not declare is an error.
- Returns:
- GradedIndexProvider
The same physical law and discretisation with a constant radius.
- Raises:
- ModeError
If a name is unknown or the radius is invalid.
- property channel_labels: tuple[ChannelLabel, ...][source]#
Return one label per requested radial channel, in solve order.
- Returns:
- tuple of ChannelLabel
The sector’s family and azimuthal order with radial order
1..count, in the ordersolve()returns the channels, which is decreasing propagation constant. A radial sector has no parity partner and no handedness, so both areNone.
Examples
>>> from solprop.modes import GradedIndexProvider, IndexMaterial >>> from solprop.modes import PowerLawPermittivity >>> provider = GradedIndexProvider( ... permittivity=PowerLawPermittivity(IndexMaterial(1.45), 0.005), ... exterior=IndexMaterial(1.44), ... radius=25e-6, ... family="TE", ... count=2, ... elements=8, ... extent=2.0, ... ) >>> [label.display_label for label in provider.channel_labels] ['TE0,1', 'TE0,2']
- core_responses: tuple[MaterialResponse, ...] = ()#
- exterior: PermittivityLaw#
- property identity: Mapping[str, JsonValue][source]#
Return physical law, sector and explicit discretisation identity.
- Returns:
- collections.abc.Mapping
Serializable physical model and construction metadata.
- node_rule(omega, z=0.0, *, n_r=None, n_theta=None)[source]#
Build nodes split at the material interface and every finite element.
The frequency is not a discretisation choice here – the mesh is the declared element count over the declared extent – but it is what the discarded power beyond the matching radius depends on, so the rule certifies that tail at this frequency, as
solprop.modes.guide.StepIndexProvider.node_rule()does. One signature for every provider.That certificate costs a solve. Building the mesh is 0.22 ms on the reference parabolic sector (32 elements, two channels, on an Apple-silicon laptop) and the whole call is 4.0 ms, because the tail bound needs the channels’ fields. It is construction-time work, once per guide rather than once per step, but a caller that builds a rule per frequency knot is paying for a solve per knot and should pass one rule instead.
- Parameters:
- omegafloat
Positive angular frequency in rad/s in the bound band; the rule’s tail bound is certified there.
- zfloat, optional
Position in m in the radius path.
- n_rint or None, optional
Gauss nodes per element, at least two;
Noneuses the four a P1 element mesh of the declared element count needs.- n_thetaint or None, optional
Angular nodes, at least two;
Nonetakes two for anLPsector of azimuthal order zero, whose fields do not depend on the angle, so that two equally spaced nodes integrate every product exactly; nine for aTE/TMsector – its Cartesian components carry one angular harmonic, whose quartic products need five – and4 * (order + 1) + 1where a higher LP angular order needs more.
- Returns:
- ModalNodeRule
Core/exterior ownership on the declared finite domain, with the exactly integrated discarded-power fraction of each channel in its identity.
- Raises:
- ModeError
If the frequency, the position or a requested channel is unusable.
- property omega_domain: tuple[float, float][source]#
Return the common material frequency interval in rad/s.
- Returns:
- tuple of float
Lower and upper angular frequency in rad/s.
- property parameter_paths: Mapping[str, ZProfile][source]#
Return the declared core-radius path in m.
- Returns:
- collections.abc.Mapping
The core_radius path in m, named as every other
ParameterisedModenames it.
- permittivity: RadialPermittivity#
- property regions: tuple[MaterialRegion, ...][source]#
Return radial-core ownership and the homogeneous exterior.
- Returns:
- tuple of MaterialRegion
Ordered core and unbounded exterior ownership.
- solve(omega, z, *, nodes)[source]#
Evaluate a variational vector sector or labelled LP approximation.
- Parameters:
- omegafloat
Positive angular frequency in rad/s in the bound band.
- zfloat
Position in m in the declared radius path.
- nodesModalNodeRule
Cartesian nodes within the declared finite domain.
- Returns:
- ModalSample
Poynting-normalised E/H; boundary_residual includes the one-sided Maxwell interface trace defect. Spatial discretisation and exterior truncation need refinement. Its
validmask is allTrue: a channel too near cutoff is refused by name, not masked.
- Raises:
- ModeError
If nodes, ownership or requested bound channels are invalid.
- tail_bound(omega, z=0.0, *, outer_radius)[source]#
Return exact omitted exterior power fractions for the variational modes.
- Parameters:
- omegafloat
Positive angular frequency in rad/s within the bound band.
- zfloat, optional
Position in m in the declared radius path.
- outer_radiusfloat
Finite radius in m, at or beyond the Bessel matching radius.
- Returns:
- numpy.ndarray
Per-channel discarded power fractions, shape (n_modes,). These certify exterior quadrature truncation, not finite-element discretisation.
- Raises:
- ModeError
If the requested tail begins inside the finite-element domain.
- solprop.modes.graded_index.MAX_EXTERIOR_TAIL_FRACTION = 0.0001#
Largest share of a channel’s power admitted beyond the matching radius.
The near-cutoff guard for the radial provider, the counterpart of
solprop.modes.stepindex.PROFILE_MIN_W. It is written as a power fraction rather than as the dimensionless decaygamma * extent * radiusbecause that decay mixes the physics with the caller’s numerical choice of extent: the same mode hasgamma * extent * radiusof 26.5, 35.3 and 44.1 atextent1.5, 2 and 2.5. The fraction is the quantity that says how much of the mode the exact exterior continuation has to carry, and the provider evaluates it exactly, from the analytic modified-Bessel tail integral over the same full-domain norm the fields are normalised by.Measured at 0.0001: over every reference case of the radial-provider qualification – both sectors, both radial laws, 24 to 96 elements, matching radii 1.5/2/2.5 and contrasts 0.001/0.005/0.0098 – the largest fraction is 6.57e-6, a factor 15 below the floor, and the weakest reference channel is the second LP channel at contrast 0.001. A five-channel TE case at 48 elements puts 5.97e-8 of its last channel outside the matching radius at a 25.00 um core and 3.24e-4 at 22.98 um, so the floor refuses that channel with a factor 3.2 of margin.
The value is a judgement, not a derived bound: it is kept at 1e-4 pending verification against an observable – an overlap or a propagation constant of a near-cutoff channel converged in the matching radius – which none of those reference cases supplies. Until then a refusal near this floor is a prompt to widen
extent, not a physical statement about the channel.
- class solprop.modes.graded_index.PowerLawPermittivity(centre, contrast, exponent=2.0)[source]#
Bases:
objectDescribe a finite radial power-law permittivity profile.
- Attributes:
- centrePermittivityLaw
Material law at the axis; its relative permittivity multiplies the shape.
- contrastfloat
Dimensionless contrast Delta in (0, 0.5); eps=eps_axis*(1-2 Delta rho**p).
- exponentfloat
Shape exponent p>=2; p=2 is parabolic and p=4 is quartic.
- centre: PermittivityLaw#
- property identity: Mapping[str, JsonValue][source]#
Return the declared centre, contrast and radial exponent.
- Returns:
- collections.abc.Mapping
Serializable physical model and construction metadata.
- property material: PermittivityLaw[source]#
Return the material owning core responses.
- Returns:
- PermittivityLaw
Material law owning the core response declarations.
- property omega_domain: tuple[float, float][source]#
Return the centre material’s frequency interval in rad/s.
- Returns:
- tuple of float
Lower and upper angular frequency in rad/s.
- permittivity(omega, radial_fraction)[source]#
Evaluate the radial relative permittivity.
- Parameters:
- omegafloat
Positive angular frequency in rad/s within the centre material’s domain.
- radial_fractionnumpy.ndarray
Dimensionless core positions in [0, 1], shape (n_points,).
- Returns:
- numpy.ndarray
Complex relative permittivity, shape (n_points,).
- Raises:
- ModeError
If a core position is non-finite or outside [0, 1].
- class solprop.modes.graded_index.RadialPermittivity(*args, **kwargs)[source]#
Bases:
ProtocolEvaluate a radial material law independently of a longitudinal path.
- property identity: Mapping[str, JsonValue][source]#
Return the law’s physical and approximation identity.
- property material: PermittivityLaw[source]#
Return the material owning core responses.
- property omega_domain: tuple[float, float][source]#
Return the material frequency interval in rad/s.
- permittivity(omega, radial_fraction)[source]#
Evaluate the core’s relative permittivity.
- Parameters:
- omegafloat
Positive angular frequency in rad/s.
- radial_fractionnumpy.ndarray
Dimensionless radius divided by the declared core radius, in [0, 1].
- Returns:
- numpy.ndarray
Relative permittivity, shape (n_points,), in the optics convention.