solprop.translate.general#
The general modal route: the seam leaves of one guide, and their certificates.
A general modal guide reaches a backend as three of the four optional leaves kernel
schema 12 added – the E/H reference and its execution
maps (transform.modal_tables), the basis metric (linear.modal_metric) and the
per-region response (responses.regional_responses) – plus the ordinary diagonal
linear operator every modal route has. GeneralModalRoute is what
solprop.translate.problem.assemble() is handed: the leaves that were built
together, with the certificate that binds them.
The fourth leaf, linear.coupled_flow, is filled for exactly one case: a
declared unitary basis of a split block,
where U.H diag(beta) U is not diagonal and the channels genuinely beat. The
route carries the transformed generator relative to one reference channel
(coupled_block()) and solprop.translate.problem.assemble() turns it into
the leaf with its certificate, because the largest step the flow’s conditioning is
declared over is the assembly’s to know. A guide in the provider’s own coordinates,
and a declared basis of an exactly degenerate block, leave it None and propagate
through the diagonal flow alone.
Module Attributes
Largest |
|
Spread of a converted |
Functions
|
Refuse a shot-noise draw in a basis it is not defined in. |
|
Return a table's coupled generator relative to one channel, or |
|
Build one guide's seam leaves on the grids a run will execute on. |
|
Return what a guide is, as a run records it and a resume compares it. |
|
Sample the reference's flux Gram at the run's own coarse bins. |
|
Return how far a sampled metric is from the identity, over chosen bins. |
|
Return the general modal identity output schema 7 persists. |
|
Return which bins a run occupies, and how heavily, for the basis gate. |
Classes
|
Own the leaves of one general modal guide and the certificate that binds them. |
- class solprop.translate.general.GeneralModalRoute(tables, responses, gram_defect, certificate_id='sampled-gram', occupied_departure=0.0, active_departure=0.0, gram_atol=0.0001, guide_identity=None, metric_tables=None, coupled_generator=None, reference_channel=0, moving_generator=None, moving_connection=None, moving_error=0.0, connection_certificate=0.0, dispersive=None, electronic=())[source]#
Bases:
DisplayedOwn the leaves of one general modal guide and the certificate that binds them.
The record a run is assembled from. It is not itself a kernel-contract field:
solprop.translate.problem.assemble()takes it apart into the three leaves of the groups they belong to, and the metric it derives from the declared Gram defect rather than storing a second copy of the same certificate.The metric is the identity unless a basis is declared. A guide built in the provider’s own coordinates is a Poynting-normalised orthogonal basis whose sampled Gram passed the construction gate of
solprop.translate.modal_tables.DenseModalTable, soW = Ito within gram_defect and the route declares the identity. A guide that declares a unitary change of basis (solprop.modes.guide.ChannelBasis) carries the dense metric metric_tables instead:W' = U.H W Uis the identity in exact arithmetic and is not the identity in the measured Gram the run actually has, so it is stored and declared rather than decorated. Either way the statistics power weight is the constant one: the Poynting amplitude is the true-power amplitude and the legacysqrt(Re n_eff)boundary is not crossed. The two leaves are different objects and both exist:linear.power_weightis the statistics boundary andlinear.modal_metricis the basis Gram.- Attributes:
- tablessolprop.translate.modal_tables.ModalTransformTables
The E/H reference and the two execution maps, tabulated on the run’s own canonical grids and zero outside the guide’s support.
- responsessolprop.translate.responses.RegionalResponseTables or None
The compiled response of each material region, or
Nonefor a guide whose materials are all linear – a propagation with no source at all, which is the linear reference case.- gram_defectfloat
The largest measured
norm(W - I, 2)of the basis the tables were sampled from, dimensionless and non-negative; the table’s owngram_defect. It is the error row of the identity metric.- certificate_idstr
Non-empty identity of the certificate gram_defect came from.
- occupied_departurefloat
The interpolated
norm(W - I, 2)over the bins this run occupies, dimensionless and non-negative. gram_defect is measured at the table’s knots; this one is measured at the run’s own coarse bins, between them, where a sampled basis is further from orthonormal – three orders further on the weakly guiding fixture (6.97e-8 against 1.14e-4). DeclaringW = Icosts a run that much insolprop.stats.physical_energy()to first order, so it is gated against gram_atol like the knot defect. Where the light is, not where the knots are sparsest: seeoccupancy_weight(). Zero on a record assembled by hand, which measures nothing and claims nothing.- active_departurefloat
The same interpolated
norm(W - I, 2), maximised over every bingrid.active_maskadmits and weighted by nothing, dimensionless and non-negative. occupied_departure discounts a bin by how little of the launched spectrum sits in it, which certifies the launch; this one certifies the run, because a broadening run can reach any active bin. It is warned on rather than gated (solprop.exceptions.GeneralModalBasisWarning), because a refusal would drop guides whose light never goes there and only the caller knows whether it will. Zero on a record assembled by hand.- gram_atolfloat
Largest defect this route will call the identity, dimensionless and positive;
solprop.translate.modal_tables.DEFAULT_GRAM_ATOLby default, which is the budgetDenseModalTablegates its own sampling with. A defect above it is refused here rather than propagated: the route is the statementW = I, and on a continuous wave the resulting error inda/dzis|1/W_00 - 1|, which is the defect itself to first order. A certificate that is merely recorded and never gated is an unbounded silent error.- guide_identitycollections.abc.Mapping or None
What the guide this route was built from is, as
guide_identity()writes it: the provider’s own identity, the sampling the reference is rebuilt from, and each material region with its declared Kerr response. It is carried here because the route is the last object that sees the guide –solprop.translate.problem.assemble()takes the leaves apart and the guide never reaches aKernelProblem– and output schema 7 persists it insidesolprop.output.schema.RunMetadata.modal.Nonefor a record built by hand, whichmodal_identity()then refuses by name rather than writing a file that cannot say what produced it.- coupled_generatornumpy.ndarray or None
The internal-convention generator of a declared split block, relative to reference_channel, in 1/m, complex, shape
(n_modes_coupled_out, n_modes_coupled_in, n_omega_coupled), exactly zero outside the run’s active band (coupled_block()).None– the ordinary case – whenever the generator is diagonal, and then the assembled problem carries nolinear.coupled_flowand propagates through the diagonal flow alone. It is not the leaf: the leaf’s conditioning certificate is declared over the largest step the run may take, which this record does not know.- reference_channelint
Which channel the cumulative
Phibeside a coupled block is built from, and therefore what coupled_generator is measured relative to. Zero, the first channel, as the coherent wall’s is; a coupled block needs aPhithat is a multiple of the identity in the channel axis, so one channel’s dispersion is carried there and every channel’s departure from it in the block.- moving_generator, moving_connectionnumpy.ndarray or None
A moving guide’s flow: the Chebyshev coefficients along z, on the tables’ own sections, of the internal-convention generator less the reference channel’s entrance diagonal, and of the connection
Gamma = W^-1 Sin the same amplitude, both in 1/m, complex, shape(n_intervals, n_deg, n_modes, n_modes, n_omega), zero outside the active band. Supplied together or not at all;Nonefor a snapshot, a guide that does not move.- moving_errorfloat
The relative Chebyshev tail of those expansions, or the path’s held-out error, whichever is larger, dimensionless; zero with no moving flow.
- connection_certificatefloat
The worst relative antisymmetry certificate of the measured connection,
norm(W Gamma + Gamma^H W - W', 2) / max|Gamma|, dimensionless; zero with no moving flow.- dispersivesolprop.translate.responses.DispersiveKerrTerms or None
The dispersive channels of the guide’s gas regions under one of SEP 6’s dispersive electronic policies (
solprop.modes.material.GasKerr), each with its node region, orNone. Under a carrier policy a gas region is a constant cubic in responses instead.- electronictuple of solprop.nonlinear.responses.DispersiveKerrResponse
The responses dispersive was sampled from, one per channel, each labelled
"<region>:<population>": what the run’s material manifest records. Empty without dispersive channels.- metric_tablessolprop.translate.coupled.ModalMetricTables or None
The dense metric of a guide that declares a unitary change of basis, built from the reference’s own flux Gram on the run’s coarse grid (
solprop.translate.coupled.dense_metric()), orNonefor a guide in the provider’s own coordinates, whose metric is the identity. Where it is present itsgauge_idis the tables’ composed one and its grids are the tables’ own, both checked here: a metric written on another basis or another grid than the reference it describes is not a metric of this run.
- Raises:
- TranslationError
If the defect is negative, not finite or above gram_atol, the budget is not positive and finite, the certificate is empty, the tables carry no execution map, or a supplied metric_tables is not a dense metric of these tables’ own basis and grids.
- coupled_generator: Complex[ndarray, 'n_modes_coupled_out n_modes_coupled_in n_omega_coupled'] | None = None#
- dispersive: DispersiveKerrTerms | None = None#
- electronic: tuple[DispersiveKerrResponse, ...] = ()#
- property metric: ModalMetricTables[source]#
Return the basis metric this route declares.
- Returns:
- solprop.translate.coupled.ModalMetricTables
The declared dense metric where a change of basis was declared, and otherwise the identity metric on the tables’ own grids, carrying the measured Gram defect as its error row.
- metric_tables: ModalMetricTables | None = None#
- property moving: bool[source]#
Return whether the route is a moving guide’s.
- Returns:
- bool
True when the route carries a moving flow, whose maps then move too.
- moving_connection: Complex[ndarray, 'n_intervals_link n_deg_link n_modes_link_out n_modes_link_in n_omega_link'] | None = None#
- moving_generator: Complex[ndarray, 'n_intervals_moving n_deg_moving n_modes_moving_out n_modes_moving_in n_omega_moving'] | None = None#
- property n_modes: int[source]#
Return how many channels the guide propagates.
- Returns:
- int
The channel axis of the stored reference.
- responses: RegionalResponseTables | None#
- tables: ModalTransformTables#
- solprop.translate.general.MAX_DENSE_METRIC_DEPARTURE: Final[float] = 0.001#
Largest
norm(W(omega) - I, 2)a dense metric may show and still be executed.Dimensionless. The general route propagates through the diagonal cumulative flow and measures the step controller’s norm on the coordinate amplitudes, both of which are the basis’s own quantities only where that basis is orthonormal in true power. A declared unitary change of basis of a certified reference stays there – the spectral norm is unitarily invariant, so
norm(U.H W U - I, 2) = norm(W - I, 2)exactly – and a nonunitary transform does not.The number. The quantity is measured on the run’s own coarse grid, between the table’s knots, where an interpolated basis is further from orthonormal than at the knots
solprop.translate.modal_tables.DEFAULT_GRAM_ATOLgates: the weakly guiding fixture oftests/driver/test_general_modal.py, whose knot defect is 6.97e-8, reaches 1.136e-4 there at 13 knots – three orders apart. So this budget cannot be the knot budget.What sets the margin is the departure over the *occupied* support, and it is smaller than the headline. The interpolated defect lives at the long-wavelength end of the sampled band, far outside where a run puts any light: on that fixture the worst bins are 1.729 um at 1.136e-4 and 1.685 um at 9.90e-5, while inside the 790–890 nm launch window the departure is 2.32e-7, so the latent error in a launched 835 nm 40 fs pulse’s
physical_energyis 3.70e-8 weighted by its own spectrum. That occupied quantity is whatGeneralModalRoute.occupied_departuremeasures and what gram_atol gates, on the identity route as much as on this one; this constant stays the whole-band budget, because what it exists to catch – a nonunitary transform – is nonunitary in every bin and not only where the light is. The headline number is also sampling-dependent rather than a property of the provider: at that fixture builder’s default nine knots the same block measures 4.03e-4, only 2.5 times under this budget, and the 1.5 um strand fixture measures 2.46e-5 at nine. So 1e-3 is not comfortably an order above the loosest departure a provider here produces; it is a factor of a few above a poorly sampled one and three orders below the order-one departure a nonunitary transform produces, which is the departure it exists to catch. It is the loosest of the three gates a declared basis passes – the declaration’s own 1e-12 unitarity budget (solprop.modes.guide.BASIS_UNITARY_ATOL), which the per-knot invariance check ofsolprop.translate.modal_tables.apply_channel_basis()takes as its own floor, is the tight one – and it is the one a backend can apply, since it sees the stored block and not the declaration.
- solprop.translate.general.N2_CONVERSION_RTOL: Final[float] = 0.01#
Spread of a converted
chi3this route will accept at an undeclared frequency.Relative and dimensionless: the largest
max/min - 1of the executedchi3across the run’s active band that this route will convert at a frequency nobody declared.A material region’s compiled response carries one susceptibility, so a declared
n2becomes achi3at one frequency (chi3 = 4 eps0 c n_0^2 n2 / 3) and the choice of frequency multiplies it by the square of an index ratio.One per cent is a policy number, not a derived one. It is chosen to sit comfortably below the case that motivated it – fused silica spans 2.13 % of its own
chi3between 800 nm and 2 um – with enough margin that a material like it is caught whatever band a run declares, while a noble gas below a few bar, which spans less than 0.1 % across any band, is never asked. The asymmetry that makes a low threshold cheap is that saying where costs the caller one keyword,MaterialKerr(n2=..., at=<m>), while an undeclared conversion is unrecoverable: the leaf carries one number and nothing downstream can say which frequency it came from, so the conversion is refused rather than guessed.
- solprop.translate.general.check_noise_basis(metric, *, has_noise)[source]#
Refuse a shot-noise draw in a basis it is not defined in.
The existing draw is one photon per channel per bin with a random phase, and that is a statement about an orthonormal true-power basis: only there does “one photon in this channel” mean an energy of
hbar omega. Two metrics satisfy that and are admitted:"identity"– the provider’s own Poynting-normalised coordinates, where the draw is added to the state as it stands;"dense"– a declared unitary change of basis of such a reference, where the same draw is made once in the reference basis, with the same seed and the same stream, and carried into the run’s coordinates bysolprop.noise.transformed_noise(). The total photon number per bin is exactly what it was and the per-channel numbers are redistributed, because fixed-modulus random phases are not invariant in distribution under unitary mixing. That the dense metric really is such a transform is gated where it is built – unitarity and the block’s exact degeneracy at the table, the departure from the identity at the route and again at the backend – so by the time it reaches here it is one.
A
"diagonal"metric is refused: it is a power-orthogonal basis with unequal channel norms, its per-channel energies are nothbar omega, nothing in this package builds one and no transport for it has been derived.- Parameters:
- metricsolprop.translate.coupled.ModalMetricTables or None
The basis metric the route declares, or
Nonefor a route with none.- has_noisebool
Whether the run carries a shot-noise realisation.
- Raises:
- TranslationError
If a realisation is carried and the metric is neither the identity nor the dense metric of a declared unitary change of basis.
- solprop.translate.general.coupled_block(table, grid, *, reference=0)[source]#
Return a table’s coupled generator relative to one channel, or
None.A guide whose channels do not exchange power has a diagonal generator at every bin, and then each channel’s dispersion goes into the cumulative diagonal flow and this returns
None: the ordinary route, untouched. A declared unitary basis of a split block does not, becauseU.H diag(beta) Uis diagonal only where the block’s propagation constants are equal (solprop.translate.modal_tables.apply_channel_basis()), and then what the run propagates is a matrix flow.What is returned is the whole generator less
reference’s own diagonal entry, because that is what the cumulativePhibeside a coupled block carries: the block’s exponential and the diagonal one multiply out to the same equation only wherePhiis a multiple of the identity in the channel axis, so one channel’s dispersion is carried there and every channel’s departure from it here, diagonal included. The co-moving frame cancels between the two for the same reason.It is exactly zero outside
grid.active_mask, as every leaf of the contract is: the state is masked to zero there and the table is not defined at every one of those bins.- Parameters:
- tablesolprop.translate.modal_tables.DenseModalTable
The tracked reference, in whatever basis was declared on it.
- gridsolprop.grid.TimeGrid
The run’s field grid, whose coarse bins the block is tabulated on.
- referenceint, optional
Which channel’s dispersion the diagonal flow carries; the first by default, as the coherent wall’s is.
- Returns:
- numpy.ndarray or None
The block in 1/m, complex, shape
(n_modes, n_modes, n_omega), orNonewhen the generator is diagonal to the rounding of its own propagation constants at every bin.
- Raises:
- TranslationError
If reference is not one of the table’s channels.
Examples
>>> import numpy as np >>> from solprop.grid import FieldGrid >>> from solprop.translate.general import coupled_block >>> from solprop.translate.modal_tables import sample_modal_table >>> from solprop.modes.guide import ModalGuide >>> from solprop.modes.stepindex import StepIndexMode >>> from solprop.modes.material import IndexMaterial, MaterialRegion >>> modes = [ ... StepIndexMode(3e-6, core=1.45, cladding=1.4, profile_wavelength=835e-9, ... kind=kind, n=0, m=1, parity="even") ... for kind in ("TE", "TM") ... ] >>> core, cladding = IndexMaterial(1.45), IndexMaterial(1.4) >>> guide = ModalGuide.from_step_index( ... modes, core=core, cladding=cladding, ... regions=( ... MaterialRegion("core", 0.0, 3e-6, core), ... MaterialRegion("cladding", 3e-6, None, cladding), ... ), ... ) >>> grid = FieldGrid.from_limits(1e-3, 835e-9, (800e-9, 870e-9), 60e-15) >>> active = grid.omega[grid.active_mask] >>> omega = np.linspace(float(active[0]), float(active[-1]), 4) >>> provider = guide.field_provider >>> table = sample_modal_table( ... provider, omega, np.array([0.0]), ... provider.node_rule(float(active[0]), n_r=8), gram_atol=1.0, ... ) >>> coupled_block(table, grid) is None True
- solprop.translate.general.general_modal_route(guide, grid, *, z_max, omega_reference, kerr_form='real', launch=None, margin=0.05, gram_atol=0.0001, selection=None)[source]#
Build one guide’s seam leaves on the grids a run will execute on.
The bridge between a
solprop.modes.guide.ModalGuide– physics, owned by the modes package – and the three schema-12 leaves a backend executes. The guide’s own declared sampling (solprop.modes.guide.ModalSampling) is resolved into a dense reference table, the table is evaluated onto the run’s canonical coarse and fine grids, and each material region’s declared response is compiled into the per-region leaf. Nothing here invents a resolution: the knots, the node rule and the degenerate blocks are the guide’s.The guide must span the run’s active band.
Grid.active_maskstarts at half the lowest declared frequency, so a run declared over 815–860 nm has an active band of about 756–1650 nm – a factor of 2.19 in frequency – and the cumulative operator samples every channel’s propagation constant across all of it. Outside the guide’s knots the stored reference is an explicit zero, so a run reaching there would be propagated against zeros; it is refused here instead, with the measured numbers in the message.The basis is certified where the run occupies it. The table’s construction gate measures the Gram at the knots; this route also measures it at the run’s own coarse bins, between them, over the bins the run occupies, and refuses a basis that is further from orthonormal there than gram_atol. That interpolated departure is three orders above the knot defect on a sparsely sampled guide and is the number a run actually propagates against; it is an interpolation error and falls with the knot spacing. Which bins count is
occupancy_weight()’s: launch supplies the weighting where it is known.- Parameters:
- guidesolprop.modes.guide.ModalGuide
A guide built by
solprop.modes.guide.ModalGuide.from_provider(), so that it carries the sampling its reference is rebuilt from.- gridsolprop.grid.TimeGrid
The run’s field grid, which supplies the canonical coarse and fine frequency axes, the active band and the fine temporal quadrature weight.
- z_maxfloat
Length the run covers, m, positive and finite; the tables are tabulated over
[0, z_max (1 + margin)]as every other route’s are.- omega_referencefloat
Positive angular frequency in rad/s at which a region’s declared
n2is converted to an absolutechi3– the run’s own reference frequency. A region that declareschi3ignores it.- kerr_form{‘real’, ‘analytic’}, optional
Which instantaneous cubic the regions’ Kerr responses are.
"real", the default, is the real-field cubicP = eps0 chi3 (E.E) Ethe legacy field route evaluates, third harmonic included;"analytic"is the analytic-signal form, which carries the fundamental band alone and is the tested oracle for it.- launchnumpy.ndarray or None, optional
The launched spectrum, shape
(n_modes, n_pol, n_omega), on this grid’s own frequency axis. It weights the occupied-support basis gate by where the light actually is;None, the default, falls back to the run’s declared band (occupancy_weight()). It is used for that certificate and for nothing else – no leaf carries it.- marginfloat, optional
Fraction of z_max the tables extend beyond the end, matching the linear operator’s.
- gram_atolfloat, optional
Largest departure from orthonormal this route calls the identity, passed both to the table’s construction gate and to the record.
- selectionsolprop.physdata.selection.MaterialSelection or None, optional
The run’s material selection, whose electronic policy a region’s gas fill (
GasKerr) takes: the Kerr coefficient at the carrier2 pi c / omega_reference, or SEP 6’s dispersive cubic, withkerr_form="real"its full cubic and"analytic"its number-conserving sector.NoneisMaterialSelection(). A region’s declaredMaterialKerris constant under every policy.
- Returns:
- GeneralModalRoute
The tables, the compiled per-region responses (
Nonefor a guide whose regions are all linear) and the measured Gram certificate.
- Raises:
- TranslationError
If the guide declares no sampling, the run is not on a field grid, the guide’s band does not cover the run’s active band, the interpolated basis is further from orthonormal than gram_atol over the bins the run occupies, the real cubic is asked for on a grid that cannot hold its third harmonic, a region declares an
n2with no measurement wavelength where its own index moves the convertedchi3by more thanN2_CONVERSION_RTOLacross the active band, a region declares one outside its own index model, or the assembled record does not validate.
- solprop.translate.general.guide_identity(guide)[source]#
Return what a guide is, as a run records it and a resume compares it.
The provider’s own identity – its model, its ordered channels and its materials – together with the two things the provider protocol does not declare and a run depends on: the
solprop.modes.guide.ModalSamplingthe dense reference is rebuilt from, and each material region with the Kerr response it declares. Every entry is a scalar, a string or a list of them, so that the mapping survives JSON unchanged and two processes agree on it.- Parameters:
- guidesolprop.modes.guide.ModalGuide
A guide carrying a sampling, as
from_provider()builds it.
- Returns:
- collections.abc.Mapping
JSON-serialisable identity.
- Raises:
- TranslationError
If the guide declares no sampling, so that nothing says what resolution its reference was built at.
- solprop.translate.general.interpolated_gram(table, tables)[source]#
Sample the reference’s flux Gram at the run’s own coarse bins.
The same interpolated samples the reference arrays were built from, one per coarse bin inside the guide’s band, so this block and the reference are the same object seen twice and cannot drift apart. It is what both the declared dense metric and the identity route’s occupied-support gate are measured on.
Outside the band the block is the identity, not zero and not the last knot extrapolated. The stored reference is an explicit zero there (
solprop.translate.modal_tables.modal_transform_tables()) and a run whose active band leaves the guide’s support is refused where the problem is assembled, so no state ever lives in those bins; what the record must not do is declare a singular metric there, because a zero block has a zero smallest eigenvalue, which is the record’s own way of saying “certifies no positive error or noise norm”. The identity is the honest statement that those bins carry no basis information and nothing lives in them.- Parameters:
- tablesolprop.translate.modal_tables.DenseModalTable
The tracked reference, in whatever basis it was built in.
- tablessolprop.translate.modal_tables.ModalTransformTables
The flat record, whose coarse grid the block is sampled on.
- Returns:
- numpy.ndarray
W(omega), complex128, shape(n_modes, n_modes, n_omega), dimensionless.
- solprop.translate.general.metric_departure(sampled, *, occupied=None, weight=None)[source]#
Return how far a sampled metric is from the identity, over chosen bins.
The one measure of how far a basis is from orthonormal in true power, shared by the route that builds a dense metric and by the backend that admits one, so that the declared bound and the executed check are the same quantity.
By default it is
max_omega norm(W(omega) - I, 2)over every bin, which is the right question for a declared change of basis: a nonunitary transform is nonunitary wherever it is applied. It is the wrong question for the interpolation error a sampled table has at the run’s own bins, because that error lives where the table’s knots are sparsest and a run need put no light there at all. occupied narrows the bins looked at and weight replaces the maximum by a weighted mean, so that a route can ask instead what the departure costs where its light is – which, to first order, is exactly the relative error an identity metric puts intosolprop.stats.physical_energy().- Parameters:
- samplednumpy.ndarray
The Hermitian metric per frequency, shape
(n_modes, n_modes, n_omega).- occupiednumpy.ndarray or None, optional
Boolean mask over the frequency axis selecting the bins to look at;
None, the default, looks at every bin.- weightnumpy.ndarray or None, optional
Non-negative weights over the frequency axis, of any scale. Where given, the result is
sum_k w_k d_k / sum_k w_kover the occupied bins instead ofmax_k d_k;None, the default, takes the maximum.
- Returns:
- float
Non-negative and dimensionless.
- Raises:
- TranslationError
If occupied or weight does not cover the frequency axis, a weight is negative or not finite, occupied selects no bin, or the selected weights sum to zero, so that there is no occupied support to measure over.
Examples
>>> import numpy as np >>> from solprop.translate.general import metric_departure >>> block = np.eye(2, dtype=complex)[:, :, None] * np.ones(3) >>> float(metric_departure(block)) 0.0 >>> block[0, 0, 2] = 1.5 >>> float(metric_departure(block)) 0.5 >>> float(metric_departure(block, occupied=np.array([True, True, False]))) 0.0
- solprop.translate.general.modal_identity(route, grid, *, channels, has_noise, flow=None)[source]#
Return the general modal identity output schema 7 persists.
One mapping answering, for a file read years later, every question the mode axis of a general modal run raises: which channels, in which order, with which quantum numbers; which tables, by the three declared identities and the extents of the stored reference; which basis metric and how far from orthonormal it was measured to be; which responses, by model and by the declared susceptibility of each region; which guide, by provider, sampling and materials; the shared co-moving frame; the run’s active band; the basis the noise was drawn in; and which accessors the basis admits (
solprop.stats.GENERAL_MODAL_ACCESSORS, whichsolprop.output.capabilitygates with).It goes into
solprop.output.schema.RunMetadata.modal, which is inside the schema-7 resume key, so a run continued against a changed guide, table, material or channel order is refused by the field that changed.A declared change of basis is in the key by four independent paths, so a file written in one basis cannot resume in another:
metric.kindmoves from"identity"to"dense";metric.gauge_idandtables.gauge_idboth carry the composed identity"<tracking>+<basis>"; thechannelsrows carry the handedness and lose the parity; andguide.sampling.basiscarries the declaration itself, matrix and all. The last of those is present only where a basis is declared, so the key of a guide in the provider’s own coordinates does not carry it; the first three are always compared, which is what makes that omission safe in both directions.Measured entries are quantised and declared ones are not. The metric’s Gram defect, the sampling’s profile error and the tables’ profile-error budget are the outputs of a dense solve and a reduction, so they enter at
MEASURED_DIGITSsignificant digits: a re-translation of the same guide on another BLAS moves their last bits and must not refuse a resume. A declaredchi3, a radius, a tolerance and a knot enter exactly, because a caller who changes one means to.- Parameters:
- routeGeneralModalRoute
The route the run was assembled from, carrying its guide_identity.
- gridsolprop.grid.TimeGrid
The run’s grid, whose active band the identity records.
- channelscollections.abc.Sequence
The ordered channel labels of the mode axis, one per row.
- has_noisebool
Whether the run carries a noise realisation, which fixes the reference basis the noise draw was made in.
- flowsolprop.translate.coupled.CoupledFlowTables or None, optional
The
linear.coupled_flowthe assembled problem carries, when it carries one. Its description joins the record under"flow", assolprop.translate.coupled.wall_identity()’s does, so that a resume across a changed basis is refused by the block that moved as well as by the gauge. The key is written only where a flow exists, so the key of a run without one does not carry it, exactly asguide.sampling.basisis written only where a basis is declared.
- Returns:
- collections.abc.Mapping
JSON-serialisable identity, stable across processes.
- Raises:
- TranslationError
If the route carries no guide identity, or the labels do not match the table’s channel count.
- solprop.translate.general.occupancy_weight(grid, launch)[source]#
Return which bins a run occupies, and how heavily, for the basis gate.
Two statements, in order of strength. The bins a run can occupy are
grid.active_mask: the linear operator is identically zero outside it and the hard band mask zeroes the state there once per accepted step, so a bin outside it is a bin nothing ever occupies. Where a launch is declared the weighting is that launched spectral energy density, which makes the weighted departure the first-order relative error an identity metric costs the launch’ssolprop.stats.physical_energy().The weighting is the launch and not the run. Nothing here knows what the run does with it: a broadening run occupies bins the launched spectrum discounted to nothing, and pays the basis error there in full. That is why
general_modal_route()measures the unweighted maximum overgrid.active_maskas well, and warns when it leaves the budget (solprop.exceptions.GeneralModalBasisWarning,GeneralModalRoute.active_departure).Where no launch is declared – a record assembled by hand, or a guide checked before a pulse exists – the fall-back is the run’s declared band,
grid.inband_mask, unweighted: the only statement about occupancy a grid makes on its own. It is the conservative one of the two, since a maximum over a band is never below a mean weighted inside it.- Parameters:
- gridsolprop.grid.TimeGrid
The run’s grid, whose active and in-band masks say where light can be.
- launchnumpy.ndarray or None
The launched spectrum, shape
(n_modes, n_pol, n_omega), internal convention, orNone.
- Returns:
- tuple
The occupied mask and the weights, the latter
Nonewhere no launch was declared, formetric_departure().
- Raises:
- TranslationError
If launch does not lie on this grid’s frequency axis, or carries no energy inside the active band at all.