Skip to content

Simulation

Simulation

Simulation class. Bundle of all the predefined objects that are needed for computing the potentials.

Attributes:

Name Type Description
atomic system (atomicsytem

Atomic system that we want to trap (has an atom and a hyperfine level as attributes among others)

material material

See NanoTrap.utils.materials for available materials. They can be easily added by the user.

trap trap

trap object with the beams used for the specified trap scheme.

surface surface

Plane or Cylinder, to get a local mask for the CP interaction (always computed as -C3/r**3).

data_folder str

Folder where your modes with the right formatting are saved. The class will fetch the modes corresponding to the trap in this folder (if they exist).

lmbdas_modes property readonly

Returns a list of all the wavelengths available in the modes present in the data folder

Note

Passed as property so it is updated anytime the trap is changed

exists_in_past_simulations(self)

This method checks if the simulation about to be run has already been saved in the "simulations" folder, by checking the .json parameter files.

Returns:

Type Description
(tuple)

tuple containing:

- bool : True if simulation already exists, False otherwise.
- str : Name of the file if the simulation has already been run.
Source code in nanotrappy\trapping\simulation.py
def exists_in_past_simulations(self):
    """This method checks if the simulation about to be run has already been saved in the "simulations" folder, by checking the .json parameter files.

    Returns:
        (tuple): tuple containing:

            - bool : True if simulation already exists, False otherwise.
            - str : Name of the file if the simulation has already been run.
    """
    self.set_current_params()
    try:
        os.listdir(self.data_folder + "/simulations")
    except FileNotFoundError:
        os.mkdir(self.data_folder + "/simulations")

    for file in os.listdir(self.data_folder + "/simulations"):
        if file.endswith(".json"):
            with open(self.data_folder + "/simulations/" + file) as json_file:
                params = json.load(json_file)

            # initializing compare keys
            comp_keys = ["Atomic system", "Material", "Trap wavelengths", "Considered state", "Geometry", "Surface"]

            # Compare Dictionaries on certain keys using all()
            res = all(params.get(key) == self.params.get(key) for key in comp_keys)
            if res:
                self.data_file = file[:-4] + "npy"
                self.E_file = file[:-5] + "E_field.npy"
                self.vecs_file = file[:-5] + "vecs.npy"
                return True
    return False

save(self)

Saves both the parameters dictionnary into a .json file and the potentials attribute into a .npy.

Source code in nanotrappy\trapping\simulation.py
def save(self):
    """Saves both the parameters dictionnary into a .json file and the potentials attribute into a .npy."""
    if not self.already_saved:

        current_time = self.params["Time of simulation"]
        current_time = current_time.replace("/", "_")
        current_time = current_time.replace(":", "_")
        current_time = current_time.replace(" ", "_")

        filename_params = self.data_folder + "/simulations/" + str(current_time) + ".json"
        filename_data = self.data_folder + "/simulations/" + str(current_time) + ".npy"
        E_filename_data = self.data_folder + "/simulations/" + str(current_time) + "E_field.npy"
        vecs_filename_data = self.data_folder + "/simulations/" + str(current_time) + "vecs.npy"

        if not os.path.exists(os.path.dirname(filename_params)):
            try:
                os.makedirs(os.path.dirname(filename_params))
            except OSError as exc:  # Guard against race condition
                if exc.errno != errno.EEXIST:
                    raise

        with open(filename_params, "w") as fp:
            json.dump(self.params, fp)

        np.save(filename_data, self.potentials)
        np.save(E_filename_data, self.Etot)
        np.save(vecs_filename_data, self.vecs)

        self.already_saved = True
    else:
        print("This simulation has already been saved, see %s" % (self.data_file))

set_current_params(self)

Sets a dictionnary with all the relevant parameters of the Simulation object and returns it.

Returns:

Type Description
dict

parameters of the simulation

Source code in nanotrappy\trapping\simulation.py
def set_current_params(self):
    """Sets a dictionnary with all the relevant parameters of the Simulation object and returns it.

    Returns:
        dict : parameters of the simulation
    """

    self.lmbdas_params = np.array([])
    self.P_params = np.array([])

    for (k, beam) in enumerate(self.trap.beams):
        self.lmbdas_params = np.append(self.lmbdas_params, beam.get_lmbda())
        self.P_params = np.append(self.P_params, beam.get_power())
        self.lmbdas_params.resize(2 * (k + 1), refcheck=False)
        self.P_params.resize(2 * (k + 1), refcheck=False)

    self.lmbdas_params.resize(4, refcheck=False)
    self.P_params.resize(4, refcheck=False)

    lambda1pair1 = str(self.lmbdas_params[0] / nm) + " nm"
    power1pair1 = str(self.P_params[0] / mW) + " mW"
    lambda2pair1 = str(self.lmbdas_params[1] / nm) + " nm"
    power2pair1 = str(self.P_params[1] / mW) + " mW"

    lambda1pair2 = str(self.lmbdas_params[2] / nm) + " nm"
    power1pair2 = str(self.P_params[2] / mW) + " mW"
    lambda2pair2 = str(self.lmbdas_params[3] / nm) + " nm"
    power2pair2 = str(self.P_params[3] / mW) + " mW"
    now = datetime.now()
    current_time = now.strftime("%d/%m/%Y %H:%M:%S")

    self.params = {
        "Time of simulation": current_time,
        "Atomic system": {
            "species": type(self.atomicsystem.atom).__name__,
            "groundstate": str(self.atomicsystem.groundstate),
            "hyperfine level": int(self.atomicsystem.f),
        },
        "Material": str(self.material),
        "Trap wavelengths": {
            "lambda 1 pair 1": lambda1pair1,
            "lambda 2 pair 1": lambda2pair1,
            "lambda 1 pair 2": lambda1pair2,
            "lambda 2 pair 2": lambda2pair2,
        },
        "Trap powers": {
            "power 1 pair 1": power1pair1,
            "power 2 pair 1": power2pair1,
            "power 1 pair 2": power1pair2,
            "power 2 pair 2": power2pair2,
        },
        "Considered state": str(self.atomicsystem.state),
        "Geometry": {
            "2D": self.geometry.dimension == 2,
            "2D plane": self.geometry.name if self.geometry.isPlane() else None,
            "2D orthogonal coord": self.geometry.normal_coord if self.geometry.isPlane() else None,
            "1D": self.geometry.dimension == 1,
            "1D axis": self.geometry.name if self.geometry.isAxis() else None,
            "1D coord1": self.geometry.coordinates[0] if self.geometry.isAxis() else None,
            "1D coord2": self.geometry.coordinates[1] if self.geometry.isAxis() else None,
        },
        "Surface": [surface.params for surface in self.surface],
        "Data_folder": self.data_folder,
    }

    print("[INFO] Simulation parameters set")
    return self.params

set_wavelengths_indices(self)

Compares the wavelengths of the beams specified for the trap with the wavelengths of the available modes in the data folder and returns the list of the file indices that correspond. The wavelengths are rounded to 0.01 nm before comparison.

!!! note
    Passed as property so it is updated anytime the trap is changed

!!! raises
    ValueError: If at least one wavelength wanted for the trap cannot be found in the data folder.
Source code in nanotrappy\trapping\simulation.py
def set_wavelengths_indices(self):
    """Compares the wavelengths of the beams specified for the trap with the wavelengths of the available modes in the data folder and returns the list of the file indices that correspond.
    The wavelengths are rounded to 0.01 nm before comparison.

        Note:
            Passed as property so it is updated anytime the trap is changed

        Raises:
            ValueError: If at least one wavelength wanted for the trap cannot be found in the data folder.
    """
    self.wavelengths_indices = np.array([], dtype=int)
    for elem in self.trap.lmbdas:
        idx = np.where(np.isclose(self.lmbdas_modes, elem, atol=1e-11))
        if len(idx[0]) != 0:
            self.wavelengths_indices = np.append(self.wavelengths_indices, idx)
        else:
            raise ValueError(
                "Demanded wavelengths for trap not found in data folder, the possible wavelengths are the following: ",
                np.sort(self.lmbdas_modes),
            )

total_potential(self)

Uses the potentials attributes of the Simulation object for each beam to return their weighted sum with the specified powers

Returns:

Type Description
total potential

array with shape(length coordinate 1,length coordinate 2,number of possbile mf states)

Source code in nanotrappy\trapping\simulation.py
def total_potential(self):
    """Uses the potentials attributes of the Simulation object for each beam to return their weighted sum with the specified powers

    Returns:
        total potential : array with shape(length coordinate 1,length coordinate 2,number of possbile mf states)
    """
    self.total_potential_noCP = np.zeros(np.shape(self.potentials[0]), dtype="float")
    self.total_vecs = np.zeros(np.shape(self.vecs[0]), dtype="complex")
    for (i, potential) in enumerate(self.potentials):
        self.total_potential_noCP = self.total_potential_noCP + self.trap.beams[i].get_power() * potential
        self.total_vecs = self.trap.beams[i].get_power() * self.vecs[i]

    norm_total_vecs = np.linalg.norm(self.total_vecs, axis=-1)

    number_mf_levels = self.total_vecs.shape[-1]
    for m in range(number_mf_levels):
        self.total_vecs[..., m] /= norm_total_vecs

    return self.total_potential_noCP + np.dstack([self.CP] * number_mf_levels)

parse_lmbdas(data_folder)

This function opens all the .npy file of the given data_folder and stores the wavelengths of the modes in an array.

Parameters:

Name Type Description Default
data_folder str

Absolute path of the folder containing the computed available modes.

required

Returns:

Type Description
array

np array with all the available wavelengths.

Source code in nanotrappy\trapping\simulation.py
def parse_lmbdas(data_folder):
    """This function opens all the .npy file of the given data_folder and stores the wavelengths of the modes in an array.

    Args:
        data_folder (str): Absolute path of the folder containing the computed available modes.

    Returns:
        array : np array with all the available wavelengths.
    """
    lmbdas_modes = np.array([])
    files = np.array([f for f in os.listdir(data_folder) if f.endswith(".npy")])
    for filename in files:
        l = np.load(data_folder + "//" + filename, allow_pickle=True)[0]
        lmbdas_modes = np.append(lmbdas_modes, l)
    return lmbdas_modes