API
Opened this issue · 2 comments
In the current implementation, the central class is Laser
, which contains the laser profile parameters, one grid where the laser is defined and will also contain the propagator. The current API would be:
The current one
box = Box()
laser = GaussianLaser(box, ) # or any class derived from Laser
laser.propagate()
laser.write_to_file()
Manuel raised the point that, in this way, class Laser
(and its derived classes) contain a mix of numerical and physical parameters, while the laser (understand: laser profile) should only contain physical properties. So we discussed a few ways to abstract the laser profile so it can be defined with physical parameters only. This is made complicated by the variety of profiles: some profiles, e.g. from experiments, are actually only defined on a grid, so there would be some interpolation between this grid and the propagator one. Suggestions would be:
The simulation-like
This is close to the current one, just separating the laser profile. Also, in the snippet below, Lasy
could be Laser
. This may be a good improvement to the current one, but still has some limitation (having multiple grids, propagators, geometries etc. will not be naturally supported, but ofc can be done with multiple lasy
instances).
laser_profile = GaussianLaserProfile(...)
box = Box()
grid = Grid(box)
propagator = Propagator()
lasy = Lasy(laser_profile, grid, propagator, ...)
lasy.propagate() # or evaluate
lasy.rt_to_xyt()
lasy.write_to_file()
(if box
and grid
are initialised inside Lasy/Laser
, it is very close to the current one, with just the laser profile explicitly separated.)
The object-oriented one
laser = GaussianLaser(...)
grid = Grid(dim='xyt') # 3D cartesian
propagator = Propagator(laser, grid) # only propagator has a grid
propagator.propagate()
write_to_file(laser, grid, propagator) # not sure if write_to_file naturally belongs to a class
grid_rz = Grid(dim='rt') # 2D cylindrical
propagator_rz = Propagator(laser, grid_rz)
propagator_rz.propagate()
write_to_file(laser, grid_rz, propagator_rz)
Here are points that we should consider in the discussion:
- Operations supported
- Initialise
- Propagate
- Write to file
- Convert RT/XYT
- interpolate
- Do we want multiple grids/propagators?
- Do we want a
get_spectrum
function? (if yes, the third suggestion might be a bit awkward.) Or should this be in e.g. openpmd-viewer for separation of concerns?
Some alternative (more detailed) example for the simulation-like API:
# Laser definition (purely physics-related properties)
long_profile = GaussianChirpedLongitudinalProfile(tau, ...) # Longitudinal profile
trans_profile = GaussianTransverseProfile(w0, ...) # Transverse profile
laser_profile = ParaxialApproximationLaser(long_profile, trans_profile, E_laser, ...) # Combined profile
# Create numerical Grid to evaluate and propagate laser on
grid = Cartesian3DGrid(xmin, xmax, dx, t=0) # Set up a grid (can also be cylindrical)
propagator = PSATDPropagator() # Initialize numerical Propagator
# Create laser object
laser = Laser(laser_profile, grid, propagator, ...)
# Propagate and export to file
laser.propagate(t=1000.e-15) # will propagate to t
laser.export('openpmd') # will save a standardized openpmd file at current t
# Interactive evaluation
Ex, Ey = laser.evaluate(x, y, z, t=1000.e-15, quantity=['Ex', 'Ey']) # will automatically propagate to t and return fields
# Run diagnostics
laser.get_spectrum(plot=True)
Slightly changed version based on our discussion during the meeting on 06.12.2022:
# Laser definition (purely physics-related properties)
long_profile = GaussianChirpedLongitudinalProfile(tau, ...) # Longitudinal profile
trans_profile = GaussianTransverseProfile(w0, ...) # Transverse profile
laser_profile = ParaxialApproximationLaser(long_profile, trans_profile, E_laser, ...) # Combined profile
# Create lasy object that serves as a "simulation-like" object
lasy = Lasy(xmin, xmax, dx, t=0, dim='xyz', propagator='psatd', ...) # Internally creates grid and propagator objects
# Add a laser (could also add other elements in the future, e.g. a non-linear optic)
laser = lasy.add_laser(laser_profile)
# Propagate and export to file
lasy.propagate(t=1000.e-15) # will propagate to t
lasy.export('openpmd') # will save a standardized openpmd file at current t
# Interactive evaluation
Ex, Ey = lasy.evaluate(x, y, z, t=1000.e-15, quantity=['Ex', 'Ey']) # will automatically propagate to t and return fields
# Run diagnostics
lasy.get_spectrum(plot=True)