modulation-da 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- modulation_da/__init__.py +7 -0
- modulation_da/current_calculator.py +71 -0
- modulation_da/exempleBeltako.py +638 -0
- modulation_da/main.py +77 -0
- modulation_da/perturbations.py +103 -0
- modulation_da/pinn_model.py +243 -0
- modulation_da/quantum_config.py +50 -0
- modulation_da/quantum_solver.py +245 -0
- modulation_da/quantum_system.py +51 -0
- modulation_da/results_manager.py +56 -0
- modulation_da/visualization.py +48 -0
- modulation_da-0.0.1.dist-info/METADATA +90 -0
- modulation_da-0.0.1.dist-info/RECORD +16 -0
- modulation_da-0.0.1.dist-info/WHEEL +5 -0
- modulation_da-0.0.1.dist-info/entry_points.txt +2 -0
- modulation_da-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# quantum_solver.py
|
|
2
|
+
import tensorflow as tf
|
|
3
|
+
import numpy as np
|
|
4
|
+
import os
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
|
|
7
|
+
# Import correct de tous les modules
|
|
8
|
+
try:
|
|
9
|
+
from quantum_config import QuantumConfig
|
|
10
|
+
from quantum_system import QuantumSystem
|
|
11
|
+
from perturbations import PerturbationManager
|
|
12
|
+
from pinn_model import PINNModel
|
|
13
|
+
from current_calculator import CurrentCalculator
|
|
14
|
+
from results_manager import ResultsManager
|
|
15
|
+
from visualization import ResultsVisualizer
|
|
16
|
+
except ImportError as e:
|
|
17
|
+
print(f"Import error: {e}")
|
|
18
|
+
print("Make sure all module files are in the same directory")
|
|
19
|
+
raise
|
|
20
|
+
|
|
21
|
+
class QuantumPINNSolver:
|
|
22
|
+
"""Solveur principal complet qui orchestre toute la simulation"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, perturbation_type='gaussian'):
|
|
25
|
+
self.perturbation_type = perturbation_type
|
|
26
|
+
|
|
27
|
+
# Initialisation de tous les modules
|
|
28
|
+
self.config = QuantumConfig()
|
|
29
|
+
self.system = QuantumSystem(self.config)
|
|
30
|
+
self.perturbations = PerturbationManager(self.config)
|
|
31
|
+
self.pinn = PINNModel(self.config)
|
|
32
|
+
self.current_calc = CurrentCalculator(self.config, self.system)
|
|
33
|
+
self.results_mgr = ResultsManager(self.config)
|
|
34
|
+
self.visualizer = ResultsVisualizer(self.results_mgr)
|
|
35
|
+
|
|
36
|
+
# Résultats
|
|
37
|
+
self.results = None
|
|
38
|
+
|
|
39
|
+
def prepare_training_data(self, E_norm, psi_st_tensor):
|
|
40
|
+
"""Prépare les données d'entraînement pour une énergie/mode donné"""
|
|
41
|
+
t_colloc_norm = tf.random.uniform((self.pinn.N, 1),
|
|
42
|
+
minval=self.config.t_min_norm,
|
|
43
|
+
maxval=self.config.t_max_norm)
|
|
44
|
+
t_0_norm = tf.zeros((self.pinn.N_0, 1), dtype=tf.float32) + self.config.t_min_norm
|
|
45
|
+
|
|
46
|
+
# Hamiltoniens perturbés (normalisés)
|
|
47
|
+
HP_list = []
|
|
48
|
+
H_r_list = []
|
|
49
|
+
H_i_list = []
|
|
50
|
+
|
|
51
|
+
for k in range(self.pinn.N):
|
|
52
|
+
t_k_norm = float(t_colloc_norm[k, 0])
|
|
53
|
+
HP_k = self.perturbations.get_perturbation(t_k_norm, self.perturbation_type)
|
|
54
|
+
HP_list.append(HP_k)
|
|
55
|
+
|
|
56
|
+
# Hamiltonien total (normalisé)
|
|
57
|
+
H_total = HP_k + self.system.H_0 + self.system.SELF
|
|
58
|
+
H_r_list.append(np.real(H_total))
|
|
59
|
+
H_i_list.append(np.imag(H_total))
|
|
60
|
+
|
|
61
|
+
HP_tensor = tf.convert_to_tensor(np.stack(HP_list), dtype=tf.complex64)
|
|
62
|
+
H_t_r = tf.convert_to_tensor(np.stack(H_r_list), dtype=tf.float32)
|
|
63
|
+
H_t_i = tf.convert_to_tensor(np.stack(H_i_list), dtype=tf.float32)
|
|
64
|
+
|
|
65
|
+
return t_colloc_norm, t_0_norm, HP_tensor, H_t_r, H_t_i
|
|
66
|
+
|
|
67
|
+
def solve_energy_mode(self, i_energy, j_mode):
|
|
68
|
+
"""Résout pour une énergie et un mode spécifiques"""
|
|
69
|
+
print(f" Training for energy {i_energy+1}, mode {j_mode+1}...")
|
|
70
|
+
|
|
71
|
+
E_norm = self.config.E_min_norm + i_energy * self.config.dE_norm
|
|
72
|
+
psi_st = self.system.stock_psi[i_energy, j_mode, :].reshape((self.config.n, 1))
|
|
73
|
+
psi_st_tensor = tf.convert_to_tensor(psi_st, dtype=tf.complex64)
|
|
74
|
+
|
|
75
|
+
# Préparation données
|
|
76
|
+
t_colloc, t_0, HP_tensor, H_t_r, H_t_i = self.prepare_training_data(E_norm, psi_st_tensor)
|
|
77
|
+
|
|
78
|
+
# Création et entraînement du modèle
|
|
79
|
+
model = self.pinn.create_model()
|
|
80
|
+
|
|
81
|
+
# TRAINING
|
|
82
|
+
history = self.pinn.train_hybrid(model, t_colloc, t_0, E_norm,
|
|
83
|
+
psi_st_tensor, HP_tensor, H_t_r, H_t_i)
|
|
84
|
+
|
|
85
|
+
return model, history, E_norm, psi_st_tensor
|
|
86
|
+
|
|
87
|
+
def predict_and_compute_current(self, model, E_norm, psi_st_tensor):
|
|
88
|
+
"""Fait des prédictions et calcule le courant"""
|
|
89
|
+
# Grille temporelle pour prédiction (normalisée)
|
|
90
|
+
t_pred_norm_vals = np.linspace(self.config.t_min_norm, self.config.t_max_norm, self.pinn.N_pred)
|
|
91
|
+
t_pred_norm = tf.convert_to_tensor(t_pred_norm_vals.reshape(-1, 1), dtype=tf.float32)
|
|
92
|
+
|
|
93
|
+
# Hamiltoniens pour prédiction (normalisés)
|
|
94
|
+
HP_pred_list = []
|
|
95
|
+
for s in range(self.pinn.N_pred):
|
|
96
|
+
t_s_norm = t_pred_norm_vals[s]
|
|
97
|
+
HP_s = self.perturbations.get_perturbation(t_s_norm, self.perturbation_type)
|
|
98
|
+
HP_pred_list.append(HP_s)
|
|
99
|
+
|
|
100
|
+
HP_pred = tf.convert_to_tensor(np.stack(HP_pred_list), dtype=tf.complex64)
|
|
101
|
+
|
|
102
|
+
# Prédiction du réseau
|
|
103
|
+
psi_pred = model(t_pred_norm) # [N_pred, 2n]
|
|
104
|
+
u_pred = psi_pred[:, :self.config.n]
|
|
105
|
+
v_pred = psi_pred[:, self.config.n:]
|
|
106
|
+
psi_p = tf.complex(u_pred, v_pred) # [N_pred, n]
|
|
107
|
+
|
|
108
|
+
# Ajout de l'état stationnaire avec phase (normalisée)
|
|
109
|
+
arg = -E_norm * t_pred_norm_vals # Argument sans dimension
|
|
110
|
+
phase = tf.exp(1j * tf.cast(arg, tf.complex64))
|
|
111
|
+
phase = tf.expand_dims(phase, axis=-1) # [N_pred, 1]
|
|
112
|
+
|
|
113
|
+
psi_st_broadcast = tf.transpose(psi_st_tensor) # [1, n]
|
|
114
|
+
psi_total = psi_p + phase * psi_st_broadcast # [N_pred, n]
|
|
115
|
+
|
|
116
|
+
return psi_total, t_pred_norm_vals, HP_pred
|
|
117
|
+
|
|
118
|
+
def run_full_simulation(self):
|
|
119
|
+
"""Lance la simulation COMPLÈTE avec training et calcul de courant"""
|
|
120
|
+
print(f"Starting FULL simulation with {self.perturbation_type} perturbation...")
|
|
121
|
+
|
|
122
|
+
J_current = tf.zeros((self.pinn.N_pred,), dtype=tf.complex64)
|
|
123
|
+
all_histories = []
|
|
124
|
+
|
|
125
|
+
for i in range(self.config.Ne):
|
|
126
|
+
print(f"\n=== Energy {i+1}/{self.config.Ne} ===")
|
|
127
|
+
|
|
128
|
+
courant_mode = tf.zeros((self.pinn.N_pred,), dtype=tf.complex64)
|
|
129
|
+
|
|
130
|
+
for j in range(self.config.n):
|
|
131
|
+
print(f" Mode {j+1}/{self.config.n}")
|
|
132
|
+
|
|
133
|
+
model, history, E_norm, psi_st_tensor = self.solve_energy_mode(i, j)
|
|
134
|
+
all_histories.append(history)
|
|
135
|
+
|
|
136
|
+
psi_total, t_pred_norm_vals, HP_pred = self.predict_and_compute_current(model, E_norm, psi_st_tensor)
|
|
137
|
+
|
|
138
|
+
# Calcul du courant pour ce mode
|
|
139
|
+
fermi_factor = self.system.fermi_dirac(E_norm)
|
|
140
|
+
fermi_tensor = tf.convert_to_tensor(fermi_factor, dtype=tf.complex64)
|
|
141
|
+
|
|
142
|
+
# Hamiltonien total pour le courant (normalisé)
|
|
143
|
+
H_0_tensor = tf.convert_to_tensor(self.system.H_0, dtype=tf.complex64)
|
|
144
|
+
SELF_tensor = tf.convert_to_tensor(self.system.SELF, dtype=tf.complex64)
|
|
145
|
+
|
|
146
|
+
H_0_pred = tf.repeat(tf.expand_dims(H_0_tensor, axis=0), self.pinn.N_pred, axis=0)
|
|
147
|
+
SELF_pred = tf.repeat(tf.expand_dims(SELF_tensor, axis=0), self.pinn.N_pred, axis=0)
|
|
148
|
+
|
|
149
|
+
HT_pred = HP_pred + H_0_pred + SELF_pred
|
|
150
|
+
|
|
151
|
+
# Courant: J ∝ ψ₁* H₁₂ ψ₂
|
|
152
|
+
psi1_conj = tf.math.conj(psi_total[:, 1])
|
|
153
|
+
H12 = HT_pred[:, 1, 2]
|
|
154
|
+
psi2 = psi_total[:, 2]
|
|
155
|
+
|
|
156
|
+
courant_mode += fermi_tensor * psi1_conj * H12 * psi2
|
|
157
|
+
|
|
158
|
+
J_current += self.config.dE_norm * (1.0 / (2.0 * self.config.pi)) * courant_mode
|
|
159
|
+
|
|
160
|
+
J_current_norm = J_current
|
|
161
|
+
|
|
162
|
+
# Courant final
|
|
163
|
+
CJJ = -2.0 * tf.math.imag(J_current_norm)
|
|
164
|
+
|
|
165
|
+
# Conversion en unités physiques
|
|
166
|
+
CJJ_np = CJJ.numpy()
|
|
167
|
+
CJJ_physical_np = CJJ_np * self.config.current_scale
|
|
168
|
+
t_physical_vals = t_pred_norm_vals * self.config.t_scale
|
|
169
|
+
|
|
170
|
+
# Génération profil de pulse
|
|
171
|
+
pulse_profile = self.perturbations.generate_pulse_profile(t_pred_norm_vals, self.perturbation_type)
|
|
172
|
+
|
|
173
|
+
self.results = {
|
|
174
|
+
'current_normalized': CJJ_np,
|
|
175
|
+
'current_physical': CJJ_physical_np,
|
|
176
|
+
'time_normalized': t_pred_norm_vals,
|
|
177
|
+
'time_physical': t_physical_vals,
|
|
178
|
+
'pulse_profile': pulse_profile,
|
|
179
|
+
'histories': all_histories
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return self.results
|
|
183
|
+
|
|
184
|
+
def save_results(self):
|
|
185
|
+
"""Sauvegarde tous les résultats"""
|
|
186
|
+
if self.results is None:
|
|
187
|
+
raise ValueError("No results to save. Run simulation first.")
|
|
188
|
+
|
|
189
|
+
self.results_mgr.save_simulation_parameters(self.perturbation_type)
|
|
190
|
+
self.results_mgr.save_current_data(
|
|
191
|
+
self.results['time_normalized'],
|
|
192
|
+
self.results['time_physical'],
|
|
193
|
+
self.results['current_normalized'],
|
|
194
|
+
self.results['current_physical']
|
|
195
|
+
)
|
|
196
|
+
self.results_mgr.save_pulse_data(
|
|
197
|
+
self.results['time_normalized'],
|
|
198
|
+
self.results['pulse_profile'],
|
|
199
|
+
self.perturbation_type
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
print("✓ All results saved successfully")
|
|
203
|
+
|
|
204
|
+
def generate_plots(self):
|
|
205
|
+
"""Génère tous les graphiques"""
|
|
206
|
+
if self.results is None:
|
|
207
|
+
raise ValueError("No results to plot. Run simulation first.")
|
|
208
|
+
|
|
209
|
+
self.visualizer.plot_current_vs_time(
|
|
210
|
+
self.results['time_normalized'],
|
|
211
|
+
self.results['current_normalized'],
|
|
212
|
+
self.results['time_physical'],
|
|
213
|
+
self.results['current_physical'],
|
|
214
|
+
self.perturbation_type
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
self.visualizer.plot_pulse_profile(
|
|
218
|
+
self.results['time_normalized'],
|
|
219
|
+
self.results['pulse_profile'],
|
|
220
|
+
self.perturbation_type
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
print("✓ All plots generated successfully")
|
|
224
|
+
|
|
225
|
+
def get_simulation_summary(self):
|
|
226
|
+
"""Retourne un résumé de la simulation"""
|
|
227
|
+
if self.results is None:
|
|
228
|
+
return "No simulation run yet."
|
|
229
|
+
|
|
230
|
+
max_current = np.max(np.abs(self.results['current_physical']))
|
|
231
|
+
final_current = self.results['current_physical'][-1]
|
|
232
|
+
|
|
233
|
+
summary = f"""
|
|
234
|
+
=== SIMULATION SUMMARY ===
|
|
235
|
+
Perturbation type: {self.perturbation_type}
|
|
236
|
+
Simulation ID: {self.config.simulation_id}
|
|
237
|
+
Energies processed: {self.config.Ne}
|
|
238
|
+
Modes per energy: {self.config.n}
|
|
239
|
+
Total models trained: {self.config.Ne * self.config.n}
|
|
240
|
+
Max physical current: {max_current:.6e} A
|
|
241
|
+
Final physical current: {final_current:.6e} A
|
|
242
|
+
Results directory: {self.results_mgr.results_dir}
|
|
243
|
+
"""
|
|
244
|
+
|
|
245
|
+
return summary
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# quantum_system.py
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
class QuantumSystem:
|
|
5
|
+
"""Management of stationary quantum system"""
|
|
6
|
+
|
|
7
|
+
def __init__(self, config):
|
|
8
|
+
self.config = config
|
|
9
|
+
self.n = config.n
|
|
10
|
+
self._setup_hamiltonian()
|
|
11
|
+
self._solve_stationary_states()
|
|
12
|
+
|
|
13
|
+
def _setup_hamiltonian(self):
|
|
14
|
+
"""Construction of Hamiltonian matrices"""
|
|
15
|
+
molE_norm = self.config.molE / self.config.E_scale
|
|
16
|
+
tm_norm = self.config.tm / self.config.E_scale
|
|
17
|
+
|
|
18
|
+
self.H_0 = np.array([
|
|
19
|
+
[-molE_norm, 0.0, 0.0],
|
|
20
|
+
[0.0, molE_norm, tm_norm],
|
|
21
|
+
[0.0, tm_norm, molE_norm]
|
|
22
|
+
], dtype=complex)
|
|
23
|
+
|
|
24
|
+
# Self-energies
|
|
25
|
+
Gamma_norm = self.config.GammaL / self.config.E_scale
|
|
26
|
+
GammaR_norm = self.config.GammaR / self.config.E_scale
|
|
27
|
+
|
|
28
|
+
self.SELF = np.array([
|
|
29
|
+
[-1j*Gamma_norm, 0, 0],
|
|
30
|
+
[0, -1j*Gamma_norm, 0],
|
|
31
|
+
[0, 0, -1j*GammaR_norm]
|
|
32
|
+
], dtype=complex)
|
|
33
|
+
|
|
34
|
+
def _solve_stationary_states(self):
|
|
35
|
+
"""Resolution of stationary states"""
|
|
36
|
+
Ne, n = self.config.Ne, self.n
|
|
37
|
+
self.stock_psi = np.zeros((Ne, n, n), dtype=complex)
|
|
38
|
+
|
|
39
|
+
GammaL_norm = self.config.GammaL / self.config.E_scale
|
|
40
|
+
vecs = [np.eye(n)[:, j:j+1] * np.sqrt(GammaL_norm) for j in range(n)]
|
|
41
|
+
|
|
42
|
+
for i in range(Ne):
|
|
43
|
+
E_norm = self.config.E_min_norm + i * self.config.dE_norm
|
|
44
|
+
GR = np.linalg.inv(E_norm * np.eye(n) - self.H_0 - self.SELF)
|
|
45
|
+
|
|
46
|
+
for j in range(n):
|
|
47
|
+
self.stock_psi[i, j, :] = (GR @ vecs[j])[:, 0]
|
|
48
|
+
|
|
49
|
+
def fermi_dirac(self, E_norm):
|
|
50
|
+
"""Fermi-Dirac distribution"""
|
|
51
|
+
return 1.0 / (1.0 + np.exp((E_norm - self.config.Ef_norm) / self.config.KBT_norm))
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# results_manager.py
|
|
2
|
+
import numpy as np
|
|
3
|
+
import os
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
|
|
6
|
+
class ResultsManager:
|
|
7
|
+
"""Complete results management and saving"""
|
|
8
|
+
|
|
9
|
+
def __init__(self, config):
|
|
10
|
+
self.config = config
|
|
11
|
+
self.results_dir = f"RESULTS_{config.simulation_id}"
|
|
12
|
+
os.makedirs(self.results_dir, exist_ok=True)
|
|
13
|
+
|
|
14
|
+
def save_simulation_parameters(self, perturbation_type):
|
|
15
|
+
"""Saves simulation parameters"""
|
|
16
|
+
end_time = datetime.now()
|
|
17
|
+
duration = end_time - self.config.start_time
|
|
18
|
+
|
|
19
|
+
params = {
|
|
20
|
+
'start_time': self.config.start_time.strftime("%Y-%m-%d %H:%M:%S"),
|
|
21
|
+
'end_time': end_time.strftime("%Y-%m-%d %H:%M:%S"),
|
|
22
|
+
'duration_seconds': duration.total_seconds(),
|
|
23
|
+
'perturbation_type': perturbation_type,
|
|
24
|
+
't_min_physical': self.config.t_min,
|
|
25
|
+
't_max_physical': self.config.t_max,
|
|
26
|
+
't_min_normalized': self.config.t_min_norm,
|
|
27
|
+
't_max_normalized': self.config.t_max_norm,
|
|
28
|
+
'E_scale': self.config.E_scale,
|
|
29
|
+
't_scale': self.config.t_scale,
|
|
30
|
+
'current_scale': self.config.current_scale,
|
|
31
|
+
'n_modes': self.config.n,
|
|
32
|
+
'n_energies': self.config.Ne
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
with open(f"{self.results_dir}/simulation_parameters.txt", "w") as f:
|
|
36
|
+
f.write("=== QUANTUM PINN SIMULATION PARAMETERS ===\n\n")
|
|
37
|
+
for key, value in params.items():
|
|
38
|
+
f.write(f"{key}: {value}\n")
|
|
39
|
+
|
|
40
|
+
def save_current_data(self, t_norm, t_physical, current_norm, current_physical):
|
|
41
|
+
"""Saves current data"""
|
|
42
|
+
# Normalized data
|
|
43
|
+
np.savetxt(f"{self.results_dir}/current_normalized.dat",
|
|
44
|
+
np.column_stack((t_norm, current_norm)),
|
|
45
|
+
header="Time_normalized Current_normalized", fmt='%.10e')
|
|
46
|
+
|
|
47
|
+
# Physical data
|
|
48
|
+
np.savetxt(f"{self.results_dir}/current_physical.dat",
|
|
49
|
+
np.column_stack((t_physical, current_physical)),
|
|
50
|
+
header="Time_seconds Current_amperes", fmt='%.10e')
|
|
51
|
+
|
|
52
|
+
def save_pulse_data(self, t_norm, pulse_profile, perturbation_type):
|
|
53
|
+
"""Saves pulse profile"""
|
|
54
|
+
np.savetxt(f"{self.results_dir}/pulse_profile_{perturbation_type}.dat",
|
|
55
|
+
np.column_stack((t_norm, pulse_profile)),
|
|
56
|
+
header="Time_normalized Pulse_amplitude", fmt='%.10e')
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# visualization.py
|
|
2
|
+
import matplotlib.pyplot as plt
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
class ResultsVisualizer:
|
|
6
|
+
"""Complete visualization of results"""
|
|
7
|
+
|
|
8
|
+
def __init__(self, results_manager):
|
|
9
|
+
self.results_manager = results_manager
|
|
10
|
+
|
|
11
|
+
def plot_current_vs_time(self, t_norm, current_norm, t_physical, current_physical, perturbation_type):
|
|
12
|
+
"""Plot of current as a function of time"""
|
|
13
|
+
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10))
|
|
14
|
+
|
|
15
|
+
# Normalized current
|
|
16
|
+
ax1.plot(t_norm, current_norm, 'b-', linewidth=2, label='Courant normalisé')
|
|
17
|
+
ax1.set_xlabel('Temps normalisé')
|
|
18
|
+
ax1.set_ylabel('Courant normalisé')
|
|
19
|
+
ax1.set_title(f'Courant normalisé - Perturbation {perturbation_type}')
|
|
20
|
+
ax1.grid(True, alpha=0.3)
|
|
21
|
+
ax1.legend()
|
|
22
|
+
|
|
23
|
+
# Physical current
|
|
24
|
+
ax2.plot(t_physical * 1e15, current_physical, 'r-', linewidth=2, label='Courant physique')
|
|
25
|
+
ax2.set_xlabel('Temps (fs)')
|
|
26
|
+
ax2.set_ylabel('Courant (A)')
|
|
27
|
+
ax2.set_title(f'Courant physique - Perturbation {perturbation_type}')
|
|
28
|
+
ax2.grid(True, alpha=0.3)
|
|
29
|
+
ax2.legend()
|
|
30
|
+
|
|
31
|
+
plt.tight_layout()
|
|
32
|
+
plt.savefig(f"{self.results_manager.results_dir}/current_vs_time_{perturbation_type}.png",
|
|
33
|
+
dpi=300, bbox_inches='tight')
|
|
34
|
+
plt.close()
|
|
35
|
+
|
|
36
|
+
def plot_pulse_profile(self, t_norm, pulse_profile, perturbation_type):
|
|
37
|
+
"""Plot of pulse profile"""
|
|
38
|
+
plt.figure(figsize=(10, 6))
|
|
39
|
+
plt.plot(t_norm, pulse_profile, 'g-', linewidth=2,
|
|
40
|
+
label=f'Perturbation {perturbation_type}')
|
|
41
|
+
plt.xlabel('Temps normalisé')
|
|
42
|
+
plt.ylabel('Amplitude de perturbation')
|
|
43
|
+
plt.title(f'Profil de perturbation - {perturbation_type}')
|
|
44
|
+
plt.grid(True, alpha=0.3)
|
|
45
|
+
plt.legend()
|
|
46
|
+
plt.savefig(f"{self.results_manager.results_dir}/pulse_profile_{perturbation_type}.png",
|
|
47
|
+
dpi=300, bbox_inches='tight')
|
|
48
|
+
plt.close()
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: modulation-da
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A scientific computing package for simulating donor-acceptor modulation.
|
|
5
|
+
Author-email: Delchere DON-TSA <dontsadelchere2000@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
13
|
+
Requires-Python: >=3.8
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
Requires-Dist: tensorflow
|
|
16
|
+
Requires-Dist: numpy
|
|
17
|
+
Requires-Dist: matplotlib
|
|
18
|
+
Requires-Dist: scipy
|
|
19
|
+
|
|
20
|
+
# Simulation de la Modulation Donneur-Accepteur par Réseaux de Neurones Informés par la Physique (PINN)
|
|
21
|
+
|
|
22
|
+

|
|
23
|
+
|
|
24
|
+
## Description
|
|
25
|
+
|
|
26
|
+
Ce projet met en œuvre un solveur basé sur les Réseaux de Neurones Informés par la Physique (PINNs) pour simuler et analyser les systèmes quantiques de type donneur-accepteur. Le code permet de configurer, perturber et résoudre les équations de Schrödinger pour de tels systèmes afin de calculer le courant résultant.
|
|
27
|
+
|
|
28
|
+
## Table des matières
|
|
29
|
+
|
|
30
|
+
- [Installation](#installation)
|
|
31
|
+
- [Utilisation](#utilisation)
|
|
32
|
+
- [Structure du Projet](#structure-du-projet)
|
|
33
|
+
- [Dépendances](#dépendances)
|
|
34
|
+
- [Auteurs](#auteurs)
|
|
35
|
+
- [Licence](#licence)
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
1. Assurez-vous d'avoir les fichiers du projet dans un dossier sur votre machine.
|
|
40
|
+
|
|
41
|
+
2. Ouvrez un terminal, naviguez jusqu'au dossier racine du projet, puis installez les dépendances et le package :
|
|
42
|
+
```sh
|
|
43
|
+
pip install -e .
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Utilisation
|
|
47
|
+
|
|
48
|
+
Le script principal pour lancer une simulation est `main.py`. Vous pouvez le configurer et l'exécuter directement.
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
python main.py
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Vous pouvez modifier le fichier `quantum_config.py` pour ajuster les paramètres de la simulation (potentiel, discrétisation, etc.) ou `perturbations.py` pour changer la nature des perturbations appliquées.
|
|
55
|
+
|
|
56
|
+
Les résultats, y compris les graphiques, sont sauvegardés dans un dossier horodaté dans le répertoire `RESULTS_*`.
|
|
57
|
+
|
|
58
|
+
## Structure du Projet
|
|
59
|
+
|
|
60
|
+
Voici une description des fichiers clés du projet :
|
|
61
|
+
|
|
62
|
+
- `main.py`: Point d'entrée principal du programme. Orchestre la configuration, la simulation et la visualisation.
|
|
63
|
+
- `quantum_config.py`: Définit les constantes et les paramètres de la simulation quantique.
|
|
64
|
+
- `quantum_system.py`: Modélise le système quantique, y compris le potentiel et l'hamiltonien.
|
|
65
|
+
- `perturbations.py`: Gère l'application de perturbations au système.
|
|
66
|
+
- `pinn_model.py`: Contient l'architecture du modèle de réseau de neurones (PINN) avec TensorFlow.
|
|
67
|
+
- `quantum_solver.py`: Le cœur du solveur, qui utilise le PINN pour résoudre les équations.
|
|
68
|
+
- `current_calculator.py`: Calcule le courant à partir des résultats de la simulation.
|
|
69
|
+
- `results_manager.py`: S'occupe de la sauvegarde des résultats (données et figures).
|
|
70
|
+
- `visualization.py`: Génère les graphiques pour visualiser les résultats.
|
|
71
|
+
- `pyproject.toml`: Fichier de configuration du projet et de ses dépendances pour la distribution.
|
|
72
|
+
|
|
73
|
+
## Dépendances
|
|
74
|
+
|
|
75
|
+
Les principales dépendances de ce projet sont :
|
|
76
|
+
|
|
77
|
+
- `tensorflow`
|
|
78
|
+
- `numpy`
|
|
79
|
+
- `matplotlib`
|
|
80
|
+
- `scipy`
|
|
81
|
+
|
|
82
|
+
## Auteurs
|
|
83
|
+
|
|
84
|
+
- **[Votre Nom]** - *[you@example.com](mailto:you@example.com)*
|
|
85
|
+
|
|
86
|
+
Veuillez modifier cette section pour ajouter les auteurs.
|
|
87
|
+
|
|
88
|
+
## Licence
|
|
89
|
+
|
|
90
|
+
Ce projet est sous licence MIT. Voir le fichier `pyproject.toml` pour plus de détails.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
modulation_da/__init__.py,sha256=E8_6ged9RNfh4IUcmwjt9EzQHG1u9Bm-ClP9v_i81Yc,159
|
|
2
|
+
modulation_da/current_calculator.py,sha256=xhdkUoQR4egdZ-7vhM2KxN2AHzMVPB48JNDBTM94jsc,3125
|
|
3
|
+
modulation_da/exempleBeltako.py,sha256=CO_n4-3rjfCtOQ7olVdKOAz_ZtRt6AeVJkow0LCCsQw,27013
|
|
4
|
+
modulation_da/main.py,sha256=9DMR6N9i4jitMertg035Ay0Ey6Qf82YLY1CjjGtQ670,2450
|
|
5
|
+
modulation_da/perturbations.py,sha256=3Qp4ZJE9RTDrSJamhCIbiv5dlrN_KTLcl5fCeN8oMpM,3988
|
|
6
|
+
modulation_da/pinn_model.py,sha256=fzWelYobNQV_QXjayDZNs-JGi2GT-wbp1HeikoRt2sk,9726
|
|
7
|
+
modulation_da/quantum_config.py,sha256=5hyJNF5a70Fv7e4fcpQbJNR5E9eDwaqtEaEEol1okkg,1668
|
|
8
|
+
modulation_da/quantum_solver.py,sha256=dUKesjEb_8VR2din18SB2JcriHGYbtR7U5UM6mzKdSw,9866
|
|
9
|
+
modulation_da/quantum_system.py,sha256=TqdD7-EDq05D9DjC3IbUQO4NJDK9BCX3nVX-coWa5oo,1790
|
|
10
|
+
modulation_da/results_manager.py,sha256=ebg17tJVLAPLIWC4eJy3ljHqenvhAfoqEFhN--669k4,2410
|
|
11
|
+
modulation_da/visualization.py,sha256=c3gBl5Ze9v8Q0vKMgTLO7H8_RB5QJnPBLIlHThiT-b8,2002
|
|
12
|
+
modulation_da-0.0.1.dist-info/METADATA,sha256=ZREuci4FGm09XncX_-RwaHyWtVWg5kSd7OKq73dx1mw,3627
|
|
13
|
+
modulation_da-0.0.1.dist-info/WHEEL,sha256=YLJXdYXQ2FQ0Uqn2J-6iEIC-3iOey8lH3xCtvFLkd8Q,91
|
|
14
|
+
modulation_da-0.0.1.dist-info/entry_points.txt,sha256=wprE_oFV8W0RuVdTYzp0eAzsN73ceM5oxoVb_I2uJsg,58
|
|
15
|
+
modulation_da-0.0.1.dist-info/top_level.txt,sha256=pEI_jdlzE5ji_jhW0D32NYmImPd5ImuuC_mxcxdC67A,14
|
|
16
|
+
modulation_da-0.0.1.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
modulation_da
|