Giter Site home page Giter Site logo

lasy's People

Contributors

angelfp avatar ax3l avatar cdmccombs avatar hightower8083 avatar iliancs avatar kale-j avatar lucafedeli88 avatar maxthevenet avatar nadezhdakhachat avatar paaaaarth avatar pre-commit-ci[bot] avatar remilehe avatar rob-shalloo avatar rtsandberg avatar soerenjalas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lasy's Issues

`laser_energy` not taken into account by default

It seems that, in the default lasy example, laser_energy is actually not taken into account.
This might be confusing to the user ; we should probably implement some default behavior, or a warning that tells the user when it is not used.

Implement CI

We should at least make sure that the example does not crash.

Add automated tests for Laguerre-Gauss and Hermite-Gauss Modes

As pointed out by Remi, we should add some automated tests to the implementations of Laguerre-Gauss and Hermite-Gauss Modes.

Some things that could be added to check the modes are behaving as expected:

  • Calculate the E-field of the first ~10? 20? 100? modes and calculate their projections onto themselves and each other to show orthogonality. This will be important when it comes to modal decomposition later
  • Propagate the modes forward a fixed distance and check the propagated beam versus analytic theory

CI: systematically check the values of the fields in the openPMD file

(related to #34)

Our current CI test only dumps the field to an openPMD file and makes sure that this is not crashing.
However, it would be good to check the actual values.

Maybe we could build a template test file that would work for any profile, and then simply loop through our existing profiles and:

  • Initialize the lasy profile
  • Dump it to openPMD file (in the 2 supported geometries)
  • Read the openPMD file and check the fields.

Add Pre-Commit CI

We discussed today on Jan 6th to add pre-commit CI logic.

Tasks:

  • static python code checks
  • include checks
  • minimize notebooks (remove output cells)
  • ensure no large files are included
  • black auto-format Python code & docs

Further Improvements to Documentation

Just collating some next steps regarding the documentation:

  • We should decide on the format for examples. A good idea from Ángel (who has implemented this on Wake-T) is to write the page, including python code and rst code into a .py file in a tutorial folder and then have sphinx autogenerate the page. An example is here: https://github.com/AngelFP/Wake-T/blob/master/tutorials/01_single_plasma_simulation.py with the rendering here https://wake-t.readthedocs.io/en/latest/tutorials/01_single_plasma_simulation.html#sphx-glr-tutorials-01-single-plasma-simulation-py
  • It would be good to have a handful tutorials covering as broad a range of the code as possible. Perhaps if we can streamline/simplify the creation process then we can add more tutorials as good first issues
  • The Overview of the Code section would be, I think, quite a nice place to elaborate on the reason for developing the code as well as some documentation relating to the standards adopted in the output files, representations of the pulse internal (similar to our recent z vs t representation discussion) etc etc. It would be nice if the basics were clear and easy to find without delving into the source code. We can also add a section on some general theory (perhaps for propagator or other). Also would be nice to have a list of codes (which can be updated continuously) which support lasy input

Laser phase measurement (wavefront-sensor) and non-Gaussian intensity distribution in the focal spot

Hi everyone,

It is great to know (from slack discussion) that LASY is soon going to be implemented for use in FBPIC. I am very excited about this additional powerful utility.

During the slack discussion with Remi, I mis-understood 'spectral phase' with the 'phase measured with the wave-front sensor'.

Non-uniform 'spectral-phase' tells that the laser pulse is not compressed to Fourier limit, however, it can not give any information about laser spot (please correct me if I am wrong). It is nicely available for use in the code (Paraxial_Approximation_Laser).

On the other hand, the non-uniform phase distribution, measured by wave-front sensor, tells how much the focal spot is deviated from Gaussian one (please correct me if I am wrong).

Do you think that we can load the phase distribution information measured by wave-front sensor in code and calculate the real intensity distribution in the laser spot. If this can be done, it will be extremely powerful and realistic.

Thank you and my best wishes to the entire team.

API

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?

Replace `scc.c` with `c` etc.

As agreed offline, let's replace

import scipy.constants as scc
scc.m_e*scc.c**2

with

from scipy.constants import c, m_e
m_e*c**2

consistently across the code.

Milestone: from FBPIC output to HiPACE++ input

This needs the following operations:

  1. Generate a RZ profile from the output of an FBPIC simulation
  2. Convert from RZ to 3D
  3. Write 3D output at lasy format
  4. Read profile in HiPACE++

This requires the following new capabilities:

  • (required, in lasy) Read input from openPMD file. It is not clear to me whether we should have 1 reader per code or 1 for all openPMD-based files. I would recommend trying the latter, and we could pass a few arguments or just the code name to fix the parameters that may differ between codes (z or t representation, field stored, E vs. a0, RZ vs. 3D, etc.)
  • (required, in lasy) dummy converter z = -c*t. As HiPACE++ currently reverts this operation exactly, that could be a trick to make the this z-to-z pipeline fully accurate and computationally cheap. [Maxence]
  • (required, in lasy, but can rely on openPMD-viewer) Convert from electric field to electric field envelope. [Maxence]
  • Convert from RZ to 3D (this is probably already implemented)

There are other ways to make this work, including supporting RZ input in HiPACE++, but I think it is preferable to do such
operations in LASY at the moment.

Start with or without azimuthal decomposition?

In my understanding, LASY should absolutely support cylindrical + azimuthal decomposition (please let me know if someone disagrees). Do we want to support it from the beginning, or start with axisymmetric and add the decomposition later? I have a preference for the latter, as I believe that having a fully working axisymmetric implementation asap will help us develop all the rest of the code (output, profiles, etc. and only afterwards correct it for azimuthal decomposition).

A practical point: multiple modes in the azimuthal decomposition could be handled by this argument

ncomps : int

Should we start with axisymmetric profiles only? Please vote (thumbs-up/down) below.

Follow-up on openPMD reader

PR #151 proposes a main implementation for the openPMD reader. Here are things that should be added in follow-up PRs, because they require separate changes, or because they rely on things not yet implemented

  • Call converters from #155
  • Add CI (will rely on converters)
  • Better wavelength handling (re-define field if user provides an envelope)

Avoid storing the same quantities in multiple places

Some quantities are stored in multiple places.
For instance, dim is stored at the Laser level and at the Box level.

Should we remove this duplication and only store these quantity ones (to avoid potential incoherence if the user tries to update these objects)?

Decomposition of experimentally measured transverse intensity profiles into set of high-order gaussians

One nice way to incorporate experimentally measured transverse intensity profiles (such as focal spot images, near field profiles or anything in between) would be to decompose it into a set of Hermite-Gaussian modes. These higher-order gaussian modes are a natural choice for data taken with a camera.

The process envisaged to get the data in would be:

  • take an experimental image provided by the user
  • Perform some background subtraction (or leave that up to the user)
  • Perform a hermite gauss decomposition to get a set of mode coefficients
  • Save either an xyz grid of data or perhaps just keep the coefficients? Alternatively, the Hermite Gauss coefficients could be converted to Laguerre-Gauss coefficients for implementing in and R,theta,Z grid.

If the data is stored as a series of coefficients, then you have effectively an analytic representation of the experimental pulse. This could be useful for speeding up propagation.

This style of method has already been implemented by LPGP, CNRS to get real pulses into FBPIC (https://journals.aps.org/prab/pdf/10.1103/PhysRevAccelBeams.25.101301) and worked quite well.

Something along these lines would be a powerful addition to LASY.

Make `box.lo`, `box.hi`, `box.dx`, etc. dictionaries?

Right now, box.lo, box.hi, etc. are list, so one needs to remember that e.g. box.lo[0] corresponds to x (in cartesian) and box.lo[2] corresponds to t, which can be quite error-prone.

Should we make them dictionaries instead (so that we would use box.lo['x'], box.lo['t'] instead)?

Add Sphinx documentation

In particular, the documentation should list the available laser profiles, along with their mathematical definition.

More features to the z-t converters

Laser.export_to_z and Laser.import_from_z do proper conversions between Z and T representations. Some additions would make it useful:

  • Include the I/O handling so LASY can output Z and T representations
  • Include the I/O handling so LASY can input Z and T representations
  • Allow dummy conversion (z = -ct) and decide on where the 0 is
  • Maybe this could be put to utils? That would lighten the Laser class, but might be cumbersome, not sure.

Temporal profile from spectrum

It is common for experiments to measure the laser (intensity) spectrum. Given the spectral phase (either measured or assumed e.g. flat), one can reconstruct the temporal profile of the amplitude of the laser pulse.

Depend on a tagged/release axiprop

We cannot release lasy to PyPI until axiprop is also uploaded:
hightower8083/axiprop#8

current zip:

Uploading lasy-0.1.0-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 40.7/40.7 kB • 00:00 • 48.9 MB/s
WARNING  Error during upload. Retry with the --verbose option for more details. 
ERROR    HTTPError: 400 Bad Request from https://upload.pypi.org/legacy/        
         Invalid value for requires_dist. Error: Can't have direct dependency:  
         'axiprop @                                                             
         https://github.com/hightower8083/axiprop/archive/refs/heads/main.zip'  

same via git

Uploading lasy-0.1.0-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 40.7/40.7 kB • 00:00 • 45.7 MB/s
WARNING  Error during upload. Retry with the --verbose option for more details. 
ERROR    HTTPError: 400 Bad Request from https://upload.pypi.org/legacy/        
         Invalid value for requires_dist. Error: Can't have direct dependency:  
         'axiprop @                                                             
         git+https://github.com/hightower8083/axiprop.git@9bd516898c1cc4e1bcbfb9
         adac26f8909ec087a0'                                                    

Define box of x, y, t / r, t ?

Right know, the definition of the Box uses 'xyz' and 'rz', which somewhat suggests that the user should pass the z coordinates.

Should we instead tell the user to pass the x, y and t coordinates when defining the box (since the envelope will be internally represented and output with t), and thus remove all references to z to avoid confusions?

Template: new CI test

Depend on #53.

Once the CI framework is ready, I believe it would be useful to make a well documented and commented PR creating a CI test. This would be used as a template when a new contributor wants to add a test.

This PR could probably test a laser profile (as I suspect this is what users are most likely to contribute). The test could do the following:

  • Create the appropriate profile
  • Get the array and compare with theory

Pass Grid instead of Box + np.array

Should this

def evaluate( self, envelope, box ):

take a Grid rather than a numpy array and Box? This would still be compatible with discussions at #12, we would then have 2 functions, one taking numpy inputs, the other one a Grid. Likewise,
def write_to_openpmd_file(file_prefix, file_format, box,

and maybe even
def compute_laser_energy(envelope, box):

I can make a PR to see how it looks.

Define the envelope field somewhere

In order to avoid math errors later (esp. in the exact definition of the propagator), should we have a clear definition of the complex envelope field (used internally) somewhere? e.g.
Screen Shot 2022-12-01 at 10 16 49 PM
where p_x and p_y are the components of the (complex) polarization vector and where
Screen Shot 2022-12-01 at 10 17 35 PM
where lambda_0 is the wavelength defined by the user.

For all laser profiles, define the amplitude by passing the total laser energy?

There are different ways to define the overall amplitude of a laser e.g. with a0, e_max, etc.
However, for e.g. donut-like laser pulses, a0 is not well-defined, or at least not intuitive.

Another way which, I think, would work for any (realistic) laser profile would be to pass the total laser energy in order to define the amplitude.

Add CI tests

Depends on #53 and #54.

This is a list of tests that should be added. If you see a significant part of the code that should be tested and is not below, please add it to the list.

  • (once applicable) pip install lasy.
  • laser profile: Gaussian? import lasy, initialize a Gaussian profile and compare array with theory. Check amplitude? std? energy?
  • Same as above, for all profiles in https://github.com/LASY-org/lasy/tree/development/lasy/profiles. Related to #34.
  • Write to file: Initialise and dump a known profile to file (one tested in CI), read it with openpmd-viewer, and compare with theory. Related to #35.
  • (once applicable) propagator. Allocate a known profile, propagate, and compare with theory.
  • (once applicable) geometry convertors. Allocate arbitrary profile, convert, compare with theory.

A few additional remarks:

  • As we have multiple geometries, we should in principle duplicate all tests for rt and xyt. In practice, we'll see if we have to do that or if we can find a better solution.
  • Some tests could be done sequentially, so they could be included in a single CI tests printing each step.

Implement openPMD-compliant output

The function below should write down the envelope fields at the openPMD format.

def write_to_file(self, file_prefix="laser", file_format='hdf5'):

I believe the most basic element (field array + metadata) that need to be dumped to file should be in class Laser already, so now is a good time to address this issue.

As suggested in comments in there, the openPMD-api handling could be put in a separate function called in there.

Write a standard at ReStructured Text (RST) or MarkDown (MD) format

One point of discussion was the kind of output we would support (electric field/vector potential, envelope/full field, etc.). In particular, we mentioned the following 3 options (I believe we were leaning towards the last one, but I am not sure we reached a final conclusion):

  • Implement multiple types of output, and let the codes choose
  • Implement one single type of output
  • Define one standard that the codes can implement, but enable other options for convenience.

For this issue, I propose to write a file (e.g. standard/standard.rst) to propose a standard. This should be a good way for discussing it until we converge to something.

As a reminder, the various points and options are:

  • Electric field or vector potential?
  • Envelope or electric field (with fast oscillations)?
  • Represent laser complex numbers as (real, imag) or (modulus, argument)?
  • 1 complex array or 2 real arrays?
  • Ex and Ey separately, or scalar field and polarization vector?
  • What is the fast index?

A few general points that should be in there:

  • The laser propagates in the z direction: for another direction, this has to be handled by the code
  • ??

Should all profiles support rt and xyt representations?

In principle, it would be great if all profiles could support both representations, for consistency. However, this may be a bit awkward in some cases, e.g. for Hermite-Gauss (meant for Cartesian coordinates) and Laguerre-Gauss (meant for cylindrical coordinates).

One general solution could be to:

  • Whenever possible/meaningful, support both representations; and
  • Implement converters RT_to_XYT and XYT_to_RT

This would be general enough to support a number of workflows that are IMO important, e.g.:

  1. Read a 3D experimental profile, decompose it into modes and send it into an FBPIC simulation;
  2. Add some spatio-temporal couplings (STCs) to a simple (maybe axisymmetric) profile, and dump it to a 3D grid (maybe all STCs can be derived in cylindrical geometry with mode decomposition, but it may get complicated, I haven't looked into it).

This way, 3D codes only have to support Cartesian data (they can implement cylindrical, but don't have to) and likewise for cylindrical codes, without loss of generality.

Implement the propagator

The propagator is currently empty, see

def propagate(self, distance):
. I have an old propagator code that I can share, but I am sure someone has a cleaner version. A few quick points:

  • I believe Grid and Box should be used to represent data in Fourier space (currently only used for position space, but it is not specific to that)
  • The field in Fourier space should be stored as a member of the Laser class for convenience (so that, if we propagate multiple times, we don't need the forward FFT each time).

Milestone: from experimental output to FBPIC/WarpX input

This needs the following operations:

  1. Initialize a LASY profile from an experimental dataset (transverse profile at least, optionally also from measured spectrum)
  2. Convert from xyt to rt representation
  3. Propagate the laser if needed (maybe from near field to far field, or close enough?)
  4. Write RZ output at lasy format
  5. read in FBPIC/WarpX

This requires the following new capabilities (only 1 atm):

  • (required, in FBPIC) Read openPMD-compliant laser file and use it in the laser antenna
  • (required, in WarpX) Read openPMD-compliant laser file and use it in the laser antenna

General questions

Hello,

Thank you for the work on Lasy. I have been trying it, alongside Warpx and have some questions I was hoping someone can help with. The first one is on the parameter npoints; is this the number of points in the x,y,t dimensions that will also be used in the Warpx simulation? Do these numbers need to be equal the number of grid points in my Warpx simulation? Is increasing the number of points better or worse for my simulation? Another parameter that has been confusing is the t_peak, on paper I know what it is but conceptually I’m a little lost. I’m used to just having my laser be there without having this parameter. I know that when the value of t_peak is too low my gaussian profile starts at a high intensity and loses its shape. Is there a way to calculate t_peak so that my pulse is nice and gaussian ?

Spatio-temporal coupling

Although many profiles are separable in longitudinal and transverse profiles E(x,y,t) = f(x,y) * g(t), some cannot, e.g. in the presence of pulse front tilt. Here, we include spatio-temporal coupling (STC) as well as a number of general effects that lead to STC (please complete the list):

  • spatial chirp
  • temporal chirp / group delay dispersion
  • Angular chirp / angular dispersion
  • pulse front tilt
  • pulse front curvature

LASY should support the main STCs, and how this is included is probably worth a discussion. A suggestion:

  • For a Gaussian profile, these terms are fully analytic and could be included in a full 3D Gaussian profile
  • For other profiles, class Laser could have the option to multiply the envelope array by phase terms at any point, which should be enough (to be checked) for all STC.

The description above assumes 3D XYT for the sake of simplicity, but some STC are also relevant for 2D RT.

More info in https://opg.optica.org/oe/fulltext.cfm?uri=oe-12-19-4399&id=81164

Make `t` the slowest varying index, in 3D meshes?

When reading the data from a lasy-produced file, a full PIC code might want t to be slowest-varying variable, since it will be taking slices at fixed t, to feed the laser antenna.

Therefore, we might consider storing the laser field already in this format, in the openPMD file.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.