thunder4d.design

The design helper (see Design helper). Everything below is importable from thunder4d.design; the sections name the submodule that defines it. Every field of the problem blocks, with its default, is defined in thunder4d.design.specs.

from thunder4d.design import (
    DesignProblem, LaserSpec, Target, Max, Min, Off,
    MPCDesigner, Candidate, starting_points, evaluate,
    Fast1DQuick, AnalyticQuick, design_map, validate_4d, to_input, export_input,
)
from thunder4d.design.catalog import GASES, MIRRORS, Coating, Gas, register_mirror, load_catalog

Problem description

class thunder4d.design.specs.DesignProblem(laser=LaserSpec(), target=Target(), constraints=Constraints(), losses=Losses(), search=SearchSpace(), refinement=Refinement(), tolerance=Tolerance())[source]

Everything the helper needs, in one object. to_dict() gives a plain dictionary (written in the JSON export).

class thunder4d.design.specs.LaserSpec(energy_J=1e-3, duration_fs=300.0, wavelength_nm=1030.0, tl_duration_fs=None, shape='gaussian', prechirp_gdd_fs2=0.0, prechirp_tod_fs3=0.0, rep_rate_Hz=1e3, polarization='linear', name='laser')[source]

The injected pulse. Properties lambda0 [m], peak_power_W, average_power_W, n2_polarization_factor (1 for linear, 2/3 for circular polarisation).

classmethod preset(name, **overrides)[source]

A laser from LASER_PRESETS, any field overridable.

thunder4d.design.specs.LASER_PRESETS

Datasheet presets (PHAROS-PH2, CARBIDE, Dira, and mpc1_18mJ_350fs), as a dictionary of LaserSpec fields.

thunder4d.design.specs.register_laser_preset(name, **fields)[source]

Add a preset.

class thunder4d.design.specs.Target(objective='max_peak_power', target_duration_fs=None, target_compression=None, weights={...}, min_throughput=Min(0.8, mode='soft'), min_main_peak_fraction=Min(0.7, mode='soft'))[source]

What the design should achieve. objective is "shortest", "max_peak_power", "target_duration", "target_compression" or "weighted".

class thunder4d.design.specs.Limit(value=None, bound='max', mode='hard', safety=1.0, weight=1.0)[source]

One constraint. allowed(default=None) is the limit actually applied (value * safety for a maximum, value / safety for a minimum, default if value is None); slack(x, default=None) the margin relative to it (negative: violated); penalty(x, default=None) is 0 if satisfied, infinity for a violated hard limit and weight * margin**2 for a violated soft one.

thunder4d.design.specs.Max(value=None, mode='hard', safety=1.0, weight=1.0)[source]
thunder4d.design.specs.Min(value=None, mode='hard', safety=1.0, weight=1.0)[source]
thunder4d.design.specs.Off()[source]

A maximum, a minimum, a disabled limit.

class thunder4d.design.specs.Constraints(space, mirrors, kerr, ionization, spots, pressure, gas)[source]

What the hardware takes, in seven groups: SpaceConstraints, MirrorConstraints, KerrConstraints, IonizationConstraints, SpotConstraints, PressureConstraints and GasConstraints.

class thunder4d.design.specs.SpaceConstraints(max_separation_m=Max(4.0), chamber_margin_m=0.2, max_chamber_length_m=Off(), fixed_chamber_length_m=None)[source]

Mirror separation and chamber length.

class thunder4d.design.specs.MirrorConstraints(allowed_roc_m=(0.5, 0.75, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0), allowed_diameters_inch=(3.0,), allowed_coatings=None, fluence=Max(None), bandwidth=Max(0.01), max_average_power_W=Off())[source]

The mirrors you can use, the fluence they take (None: the LIDT of the coating at the local pulse duration), the fraction of the output energy allowed outside the coating band and the average power on one mirror.

class thunder4d.design.specs.KerrConstraints(p_over_pcr=Max(0.5), b_per_pass_rad=Max(1.0), b_total_rad=Off())[source]

Peak power over the critical power, on-axis B-integral per pass and in total.

class thunder4d.design.specs.IonizationConstraints(peak_intensity_W_cm2=Max(None, safety=0.5))[source]

Peak intensity at the waist (None: the ionisation threshold of the gas).

class thunder4d.design.specs.SpotConstraints(min_spot_separation_w=Min(3.0), edge_clearance_w=Min(2.5), pattern_radius_m=None)[source]

Circular pattern of \(M\) spots on each mirror, in units of the spot radius on the mirror; the pattern radius follows the mirror size unless pattern_radius_m is given.

class thunder4d.design.specs.PressureConstraints(pressure_bar=(0.0, 3.0), resolution_bar=0.01)[source]

The pressure range the chamber takes, and the resolution of the regulator.

class thunder4d.design.specs.GasConstraints(allowed=('He', 'Ne', 'Ar', 'Kr', 'Xe', 'N2'))[source]

The gases that may be used.

class thunder4d.design.specs.Losses(mode_matching_efficiency=1.0)[source]

Fraction of the energy injected in the cell mode.

class thunder4d.design.specs.Tolerance(separation_error_mm=1.0, roc_tolerance_rel=0.005)[source]

Alignment errors for which the reports give the sensitivity (information only).

class thunder4d.design.specs.SearchSpace(gases=None, roc_m=None, diameters_inch=None, coatings=None, branches=('concentric', 'planar'), round_trips=(3, 40), k_range=None, pass_offsets=(0, -1), min_passes=5)[source]

Which geometries starting_points() enumerates.

class thunder4d.design.specs.Refinement(n_candidates=5, diversity=True, tune=('pressure_bar',), neighbour_n_passes=2, neighbour_roc_steps=0, method='nelder-mead', max_evaluations=60, xtol_rel=1e-3, keep_traces=True)[source]

How the best candidates are tuned.

Search

class thunder4d.design.designer.Candidate(gas, pressure_bar, roc_m, round_trips, k, branch='concentric', n_passes=None, diameter_inch=3.0, coating='dielectric_1030nm', prechirp_gdd_fs2=0.0)[source]

One configuration: radius of curvature, number of round trips \(M\) of the re-entrant cycle and index \(k\) give \(d = R(1 \pm \cos(\pi k/M))\); n_passes is the number of passes actually used (default \(2M\)). After an evaluation it carries metrics, slacks (margin of each limit), limits (value, operator, applied limit, mode), warnings, score, objective, penalty and violation.

separation_m

Mirror separation \(d\) [m].

report(problem=None)[source]

The text report of Design helper.

tolerances(problem=None, lambda0_m=None)[source]

Relative change of \(w_0\) and of the mirror spot for the alignment errors of problem.tolerance: {"separation": (dw0, dwm), "roc": (dw0, dwm)}.

linear_mode(lambda0_m=1030e-9)[source]

(w0, w_mirror, zR) of the empty cell [m].

to_cell(polarization_factor=1.0, lambda0_m=1030e-9, **kw)[source]

The MPC of the design, with the gas, the coating curves and the mirror diameter.

class thunder4d.design.designer.QuickResult(duration_fs, peak_power_W, throughput, main_peak_fraction=None, compressor_gdd_fs2=None, b_total_rad=None, b_per_pass_rad=None, p_over_pcr=None, peak_intensity_W_cm2=None, mirror_fluence_J_cm2=None, duration_per_bounce_fs=None, out_of_band_fraction=None, spectrum_nm=None, extras={})[source]

What a quick solver returns (Design helper).

class thunder4d.design.designer.MPCDesigner(problem, quick=None, verbose=True, workers=None)[source]
Parameters:
  • problem – a DesignProblem

  • quick – a quick solver, quick(problem, candidate) -> QuickResult

  • workers (int) – processes for the quick solver (picklable solver needed)

screen(keep=None, **starting_kw)[source]

Evaluate the starting points with the analytic estimates and keep the keep best diverse ones (default ten times n_candidates).

refine(candidates, max_attempts=None)[source]

Evaluate, tune and rank the candidates until n_candidates feasible designs are found, or max_attempts (default three times n_candidates) have been tried. Returns a DesignResult.

run(keep=None, **starting_kw)[source]

refine(screen(...)).

class thunder4d.design.designer.DesignResult(problem, screened, refined, traces)[source]

refined (the designs), screened (every evaluated starting point), traces (tuning evaluations), best (lowest score).

table(which='refined')[source]

Text table, ranked.

export(path, which=0, **kw)[source]

The design of rank which as a standard input file (see to_input()).

save_json(path)[source]

Problem and designs as JSON.

thunder4d.design.designer.starting_points(problem, gases=None, round_trips=None, k='all', p_over_pcr=0.3, verbose=True)[source]

Geometries of the search space, prefiltered, each with an analytic starting pressure.

thunder4d.design.designer.start_pressure(problem, cand, p_over_pcr=0.3)[source]

The analytic first guess of the pressure of one geometry.

thunder4d.design.designer.prefilter(problem, cand)[source]

The list of hard limits that exclude a geometry analytically (empty: it can pass).

thunder4d.design.designer.herriott_k(round_trips, k_range=None)[source]

Valid indices \(k\) for \(M\) round trips: coprime with \(M\) and \(k < M/2\).

thunder4d.design.designer.evaluate(problem, cand, metrics)[source]

Fill cand (margins, limits, warnings, score) from a dictionary of metrics: the same judgement for every solver.

Quick solvers

class thunder4d.design.fast1d_quick.Fast1DQuick(accuracy='fast', matching='linear', keep_spectrum=True, options={})[source]

Quick solver backed by fast1d (Design helper).

Parameters:
  • accuracy (str) – "fast", "default" or "fine"

  • matching (str) – "linear" or "nonlinear" injection

  • options (dict) – any other MPCInput field

simulate(problem, cand, accuracy=None)[source]

The full MPCOutput of a design (fields, spectra, plot()).

validate(problem, cand, accuracy=None, rtol=0.02, checks=('steps', 'grid', 'precision'))[source]

Convergence check of fast1d for this design.

build_input(problem, cand, accuracy=None)[source]

The MPCInput of a design.

class thunder4d.design.scan.AnalyticQuick(matching='linear')[source]

Closed-form quick solver, microseconds per cell, optimistic durations.

thunder4d.design.scan.design_map(problem, *, gas, roc_m, k=1, round_trips=None, branch='concentric', x=None, y=None, quick=None, coating=None, diameter_inch=None, pass_offset=0, workers=None)[source]

Scan two parameters and find the limiting constraint at each point (Design helper).

Parameters:
  • x – (name, values), default pressure from the pressure range

  • y – (name, values), default round trips from the search space

  • quick – None for the analytic estimates, or a solver such as Fast1DQuick()

  • round_trips – fixed \(M\), required unless round_trips is a scanned axis

Returns:

a DesignMap

class thunder4d.design.scan.DesignMap[source]

x, y, x_name, y_name, limiting, tightest, margin, values, candidates, feasible.

best()[source]

The feasible candidate with the lowest score, or None.

summary()[source]

A short text description.

plot(ax=None, contour='duration_fs', levels=None, mark=(), show_best=True)[source]

Draw the map: regions coloured by the limiting constraint, the feasible region outlined, contours of contour, and the points of mark as (x, y, label).

fast1d

The 1+1D solver, usable on its own.

class thunder4d.design.fast1d.MPCInput(energy, fwhm, wavelength=1030e-9, gas=..., pressure=..., roc=..., length=..., n_passes=20, accuracy=None, **numerics)[source]

Input of a run: SI units, one field per quantity (see the module docstring for the complete list). MPCInput.herriott(roc, N, k, branch="concentric", **kwargs) builds the geometry from \(R\), \(N\) and \(k\); with_accuracy(accuracy, **overrides) copies the input with the numerical settings of a preset. mirror_response takes the complex amplitude transfer of a bounce on the absolute angular frequency.

thunder4d.design.fast1d.simulate(inp)[source]

Propagate and compress. Returns an MPCOutput (fwhm_compressed, peak_power_compressed, gdd_compression, b_integral, transmission, intensity_max, fluence_mirror_max, per-pass arrays, fields and spectra, summary(), plot()). Raises SimulationStopped if the model breaks down.

class thunder4d.design.fast1d.MPCOutput[source]

Result of simulate(): the input, the time and frequency axes, the fields and spectra (input, output, compressed, Fourier limit), the energies and durations, gdd_compression, b_integral, peak_power_over_pcr, intensity_max, fluence_mirror_max and the per-pass arrays (pass_energy, pass_b_integral, pass_w_mirror, pass_fwhm…).

thunder4d.design.fast1d.validate(inp, checks=('steps', 'grid', 'precision'), rtol=0.02)[source]

Re-run with halved steps, a larger grid and double precision; returns a ValidationReport (ok, summary()).

exception thunder4d.design.fast1d.SimulationStopped[source]

The run was stopped by a guard (optical shock, step budget). p_over_pcr, passes_done and b_integral tell where it stopped.

exception thunder4d.design.fast1d.BeamCollapse[source]

Subclass of SimulationStopped, raised when \(P\) exceeds the critical power.

thunder4d.design.fast1d.ACCURACY

The settings of the "fast", "default" and "fine" presets.

From a design to the 4D solver

thunder4d.design.export.to_input(problem, cand, *, preset='coarse', injection='linear', name=None, window=None, precision='single', device='auto', run=None)[source]

The standard input file (thunder4d.inputfile) of a design, as a dictionary, with a design block recording its origin.

thunder4d.design.export.export_input(problem, cand, path, **kw)[source]

to_input written to path as JSON.

class thunder4d.design.export.Validation4D(cfg, rows, extra, built, fast1d, runtime_s)[source]

Result of validate_4d(): the input used, the comparison rows (quantity, fast1d, 4D, relative difference), the 4D-only results in extra, and the built simulation and the fast1d output. summary() returns the table as text and plot() the comparison figure.

thunder4d.design.export.validate_4d(problem, cand, *, quick=None, preset='coarse', verbose=True, max_seconds=None, **to_input_kw)[source]

Run the design with the 4D lens-frame solver and compare it with fast1d (Design helper). Returns a Validation4D.

Catalogues

class thunder4d.design.catalog.gases.Gas(name, ip_eV, raman_active=False, n2_1bar=None, ionization_threshold_W_cm2=None, bsi_fraction=0.2, notes='')[source]

A gas of the design catalogue. ionization_threshold is the given threshold, or bsi_fraction times the barrier-suppression intensity. material(pressure_bar, temperature_K=293.15, polarization_factor=1.0) returns the Material; with_(**changes) a modified copy.

thunder4d.design.catalog.gases.GASES

The catalogue, a dictionary of Gas.

thunder4d.design.catalog.gases.register_gas(gas, overwrite=False)[source]
thunder4d.design.catalog.gases.get_gas(name)[source]

Add a gas; get one (with an informative error).

class thunder4d.design.catalog.mirrors.Coating(name, kind='dielectric', role='cavity', band_nm=(0, inf), reflectivity=1.0, gdd_fs2=0.0, lidt_J_cm2=None, lidt_ref_fs=1000.0, lidt_exponent=0.0, pair=None, diameter_inch=(), r_in_percent=False, vendor='', source='', notes='')[source]

A mirror coating. reflectivity and gdd_fs2 are scalars or (wavelength_nm, values) tables. R(lam_nm), gdd(lam_nm) and in_band(lam_nm) evaluate them; lidt(duration_fs) is the damage threshold at a pulse duration.

classmethod from_files(name, reflectivity_csv=None, gdd_csv=None, *, delimiter=None, skip_header=0, wavelength_unit='nm', **kw)[source]

A coating from vendor curves (two columns: wavelength, value).

thunder4d.design.catalog.mirrors.MIRRORS

The catalogue, a dictionary of Coating.

thunder4d.design.catalog.mirrors.register_mirror(coating, overwrite=False)[source]
thunder4d.design.catalog.mirrors.get_mirror(name)[source]
thunder4d.design.catalog.mirrors.load_catalog(path, overwrite=True)[source]

Add a coating, get one, or register all the coatings of a JSON file (curve files are read relative to it).

thunder4d.design.catalog.mirrors.load_curve(path, delimiter=None, skip_header=0, wavelength_unit='nm')[source]

Read a two-column curve file; returns (wavelength_nm, values).