Configuration#

Here we illustrate how to create experimental configurations, using the atomsmltr.simulation.configurator subpackage

Introduction to configurations#

Configuration objects are at the heart of this package. They are the cement that allows to combine all the environment objects (lasers, magnetic fields, zones) and feed them into a simulation.

Here is how to create a configuration.

from atomsmltr.simulation import Configuration
from atomsmltr.atoms import Ytterbium

# init a configuration for ytterbium atoms
config = Configuration(atom=Ytterbium())

objects can be added to the configuration using the add_objects() method or the += operator. The Configuration object will automatically sort them according to their type.

ATTENTION objects are stored in internal dictionnaries, using their tag property as a key. Therefore, it is important to define tags for the objects and to make sure that objects do not have the same tags (otherwise, an error will be raised)

from atomsmltr.environment import Limits, MagneticOffset, MagneticGradient, GaussianLaserBeam

# let's define two lasers
laser1 = GaussianLaserBeam(tag="laser1")
laser2 = GaussianLaserBeam(tag="laser2")

# two magnetic fields
mag_offset = MagneticOffset((0,1,0), tag="offset")
mag_gradient = MagneticGradient((0,0,0), 0.5, (0,1,0), (0,0,1), tag="gradient")
# one limit
xlim = Limits(0, 10, axis=0, target="position")

# and add them
config.add_objects([laser1, mag_offset])   # we can provide a list
config.add_objects(xlim)  # a single object
config += mag_gradient, laser2  # or use the operator :)

now we can print the information

config.print_info()
Hide code cell output
# ------------ CONFIG INFO > START ------------ #
────────────────────────
| General informations |
────────────────────────
. atom :
  └── name : Ytterbium

. lasers :
  β”œβ”€β”€ laser1
  └── laser2

. magnetic fields :
  β”œβ”€β”€ offset
  └── gradient

. forces :
  └── empty

. zones :
  └── vazewa


────────────────────
| atom | ytterbium |
────────────────────
. Parameters :
  β”œβ”€β”€ mass (kg) : 2.89e-25
  └── mass (au) : 173.94

. Transition list :
  β”œβ”€β”€ main
  └── intercombination

. 'main' transition :
  β”œβ”€β”€ Ξ» : 398.91 nm
  β”œβ”€β”€ Ξ“ : 2Ο€ Γ— 2.89e+07 Hz
  β”œβ”€β”€ Isat : 59.51 mw/cmΒ²
  └── lande factor g : 1.035

. 'intercombination' transition :
  β”œβ”€β”€ Ξ» : 555.80 nm
  β”œβ”€β”€ Ξ“ : 2Ο€ Γ— 1.82e+05 Hz
  β”œβ”€β”€ Isat : 0.14 mw/cmΒ²
  └── lande factor g : 1.493


────────────────────────
| laser | tag='laser1' |
────────────────────────
. Parameters :
  β”œβ”€β”€ type : Gaussian beam
  β”œβ”€β”€ tag : laser1
  β”œβ”€β”€ waist (m) : 0.001
  β”œβ”€β”€ power (W) : 0.001
  β”œβ”€β”€ waist position (m) : [0 0 0]
  β”œβ”€β”€ direction type : vector
  β”œβ”€β”€ direction : [0 0 1]
  β”œβ”€β”€ unit vector : [0. 0. 1.]
  β”œβ”€β”€ unit vector phi : Ο€ Γ— 0.0
  β”œβ”€β”€ unit vector theta : Ο€ Γ— 0.0
  └── Rayleigh length : 7.9 m

. Polarization settings :
  └── type : Vertical

. Polarization vector :
  β”œβ”€β”€ coords : (1.00, 0.00, 0.00)
  β”œβ”€β”€ polar angle u : 0.50 pi
  └── azimt angle v : 0.00 pi

. Projections (amplitudes) :
  β”œβ”€β”€ vertical : 1.00+0.00j
  β”œβ”€β”€ horizontal : 0.00+0.00j
  β”œβ”€β”€ circular left : 0.71+0.00j
  └── circular right : 0.71+0.00j

. Projections (squared norm) :
  β”œβ”€β”€ vertical : 1.00
  β”œβ”€β”€ horizontal : 0.00
  β”œβ”€β”€ circular left : 0.50
  └── circular right : 0.50


────────────────────────
| laser | tag='laser2' |
────────────────────────
. Parameters :
  β”œβ”€β”€ type : Gaussian beam
  β”œβ”€β”€ tag : laser2
  β”œβ”€β”€ waist (m) : 0.001
  β”œβ”€β”€ power (W) : 0.001
  β”œβ”€β”€ waist position (m) : [0 0 0]
  β”œβ”€β”€ direction type : vector
  β”œβ”€β”€ direction : [0 0 1]
  β”œβ”€β”€ unit vector : [0. 0. 1.]
  β”œβ”€β”€ unit vector phi : Ο€ Γ— 0.0
  β”œβ”€β”€ unit vector theta : Ο€ Γ— 0.0
  └── Rayleigh length : 7.9 m

. Polarization settings :
  └── type : Vertical

. Polarization vector :
  β”œβ”€β”€ coords : (1.00, 0.00, 0.00)
  β”œβ”€β”€ polar angle u : 0.50 pi
  └── azimt angle v : 0.00 pi

. Projections (amplitudes) :
  β”œβ”€β”€ vertical : 1.00+0.00j
  β”œβ”€β”€ horizontal : 0.00+0.00j
  β”œβ”€β”€ circular left : 0.71+0.00j
  └── circular right : 0.71+0.00j

. Projections (squared norm) :
  β”œβ”€β”€ vertical : 1.00
  β”œβ”€β”€ horizontal : 0.00
  β”œβ”€β”€ circular left : 0.50
  └── circular right : 0.50


─────────────────────────────────
| magnetic field | tag='offset' |
─────────────────────────────────
. Parameters :
  β”œβ”€β”€ type : constant field
  β”œβ”€β”€ tag : offset
  β”œβ”€β”€ field_value (T) : [0 1 0]
  └── norm (T) : 1


───────────────────────────────────
| magnetic field | tag='gradient' |
───────────────────────────────────
. Parameters :
  β”œβ”€β”€ type : perfect gradient
  β”œβ”€β”€ tag : gradient
  β”œβ”€β”€ slope (T/m) : 0.5
  β”œβ”€β”€ gradient direction : [0. 1. 0.]
  β”œβ”€β”€ field direction : [0. 0. 1.]
  β”œβ”€β”€ origin (m) : [0 0 0]
  └── offset (T) :   0


───────────────────────
| zone | tag='vazewa' |
───────────────────────
. Parameters :
  β”œβ”€β”€ type : 1D limits
  β”œβ”€β”€ tag : vazewa
  β”œβ”€β”€ in_tag
  β”œβ”€β”€ out_tag : vazewa
  β”œβ”€β”€ target : position
  β”œβ”€β”€ action : stop
  β”œβ”€β”€ min : 0.0
  β”œβ”€β”€ max : 10.0
  β”œβ”€β”€ axis : 0
  └── inverted : False


────────────────────────
| Atom-light couplings |
────────────────────────
. transition > 'main' :
  └── empty

. transition > 'intercombination' :
  └── empty


# ------------ CONFIG INFO > STOP  ------------ #

Manage objects in a collection#

Currently, our convention is that copies of objects are stored in the configuration object. This way, if an object is modified after it has been added in the configuration, this modification won’t affect the configuration.

It might be that we change this behaviour at some point… this is to be discussed.

The configuration object comes with a lot of useful methods to manage the objects. Here are some examples ; for more information, please have a look at the API documentation

from atomsmltr.simulation import Configuration
from atomsmltr.atoms import Ytterbium
from atomsmltr.environment import Limits, MagneticOffset, MagneticGradient, GaussianLaserBeam

# - INIT
# let's define some objects
laser1 = GaussianLaserBeam(tag="laser1")
laser2 = GaussianLaserBeam(tag="laser2")
mag_offset = MagneticOffset((0,1,0), tag="offset")

# init a configuration for ytterbium atoms
config = Configuration(atom=Ytterbium())

# add objects
config += laser1, laser2, mag_offset
# - REMOVE AN OBJECT
print(config.list_lasers())
config.rm_laser("laser1")
print(config.list_lasers())
['laser1', 'laser2']
['laser2']
# - REMOVE ALL OBJECTS
# all lasers
config.rm_all_lasers()
print(config.list_lasers())
print(config.list_magnetic_fields())

# everything
config.rm_all_objects()
print(config.list_magnetic_fields())
[]
['offset']
[]
# - UPDATE AN OBJECT
# reset
config.rm_all_objects()

# add a laser > a copy is stored
laser1.wavelength = 399e-9
config += laser1

# check wavelength of laser stored
print(config.get_laser_copy("laser1").wavelength)

# update the laser > the stored version is not affected
laser1.wavelength = 556e-9
print(config.get_laser_copy("laser1").wavelength)

# to change the config, laser has to be updated
config.update_objects(laser1)
print(config.get_laser_copy("laser1").wavelength)
3.99e-07
3.99e-07
5.56e-07

Setting up atom-light couplings#

In order to give the user a full control on atom-light interactions, we decided to make the configuration object ignorant of any atom-light interaction coupling. Hence, it is not sufficient to add an atom and a laser with compatible wavelengths for the two to interact.

Atom-light coupling are given by hand using the add_atomlight_coupling() method, associating a laser and a transition using their tags.

from atomsmltr.simulation import Configuration
from atomsmltr.atoms import Ytterbium
from atomsmltr.environment import PlaneWaveLaserBeam

# init a configuration for ytterbium atoms
config = Configuration(atom=Ytterbium())

# get ytterbium main transition information
main = config.atom.trans["main"]

# create a plane wave laser
laser = PlaneWaveLaserBeam()
laser.wavelength = main.wavelength
laser.set_power_from_I(main.Isat)  # set power to have I=Isat
laser.tag = "399"

# add laser to config
config += laser

# create a coupling
config.add_atomlight_coupling(
    laser="399",
    transition="main",
    detuning=-2 * main.Gamma,
)

# show info
config.print_atomlight_info()
────────────────────────
| Atom-light couplings |
────────────────────────
. transition > 'main' :
  └── laser '399' : detuning=-3.63e+08 (-2.00Ξ“)

. transition > 'intercombination' :
  └── empty