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:
|
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