prefix = "{}_{}_amp={}_per={}__".format( state.n, state.l, amp, period) t_init = 0 t_final = 20 * period * asec window = ion.potentials.LinearRampTimeWindow( ramp_on_time=t_init + period * asec, ramp_time=5 * period * asec) e_field = ion.SineWave( omega=twopi / (period * asec), amplitude=amp * atomic_electric_field, window=window, ) internal_potential = ion.Coulomb() mask = ion.RadialCosineMask( inner_radius=(bound - 50) * bohr_radius, outer_radius=bound * bohr_radius, ) # animators = [ion.animators.CylindricalSliceAnimator(target_dir = OUT_DIR), # ion.animators.CylindricalSliceAnimator(postfix = 'log', target_dir = OUT_DIR, log = True, renormalize = False), # ion.animators.CylindricalSliceAnimator(postfix = '30', target_dir = OUT_DIR, plot_limit = 30 * bohr_radius), # ion.animators.CylindricalSliceAnimator(postfix = '100', target_dir = OUT_DIR, plot_limit = 100 * bohr_radius)] # spec = ion.mesh.CylindricalSliceSpecification(prefix + 'cyl_slice', time_initial = t_init, time_final = t_final, time_step = dt, # z_bound = bound * bohr_radius, z_points = bound * 10, # rho_bound = bound * bohr_radius, rho_points = bound * 5, # initial_state = state, # internal_potential = internal_potential, # electric_potential = e_field, # animators = animators # ) # specs.append(spec)
# window = window) spec_kwargs = dict( r_bound=bound * bohr_radius, r_points=bound * points_per_bohr_radius, l_bound=20, initial_state=ion.HydrogenBoundState(1, 0), time_initial=-t_bound * asec, time_final=(t_bound + t_extra) * asec, time_step=1 * asec, use_numeric_eigenstates=True, numeric_eigenstate_max_energy=50 * eV, numeric_eigenstate_max_angular_momentum=5, electric_potential=efield, electric_potential_dc_correction=True, mask=ion.RadialCosineMask(inner_radius=0.8 * bound * bohr_radius, outer_radius=bound * bohr_radius), store_data_every=-1, ) sim = ion.SphericalHarmonicSpecification( f"PWTest_amp={amp}aef_phase={phase / pi:3f}pi__tB={t_bound}pw__tE={t_extra}asec", **spec_kwargs, ).to_sim() sim.run() print(sim.info()) # sim.mesh.plot_g(target_dir = OUT_DIR) # sim.mesh.plot_g(target_dir = OUT_DIR, name_postfix = '_25', plot_limit = 25 * bohr_radius) # # plot_kwargs = dict(
sim = ion.LineSpecification( "fsw", x_bound=space_bound, x_points=2**14, internal_potential=pot, electric_potential=electric, test_mass=mass, test_states=test_states, dipole_gauges=(), initial_state=init, # time_initial = 0, time_final = 1000 * asec, time_step = 1 * asec, time_initial=-pw * time_bound * asec, time_final=pw * time_bound * asec, time_step=1 * asec, minimum_time_final=3 * pw * time_bound * asec, mask=ion.RadialCosineMask(inner_radius=space_bound * 0.8, outer_radius=space_bound), animators=ani, evolution_method="SO", ).to_sim() print(sim.info()) si.vis.xy_plot( "fsw_potential", sim.mesh.x_mesh, pot(distance=sim.mesh.x_mesh), x_unit="bohr_radius", y_unit="eV", x_lower_limit=-3 * width, x_upper_limit=3 * width, target_dir=OUT_DIR,
cosine_pulse = ion.potentials.GaussianPulse( pulse_width=pw, fluence=flu, phase=0, window=window ) sine_pulse = ion.potentials.GaussianPulse( pulse_width=pw, fluence=flu, phase=pi / 2, window=window ) shared_kwargs = dict( r_bound=r_bound * bohr_radius, r_points=r_bound * 4, l_bound=100, time_initial=-time_bound * pw, time_final=time_bound * pw, time_step=1 * asec, mask=ion.RadialCosineMask( inner_radius=(r_bound * 0.8) * bohr_radius, outer_radius=r_bound * bohr_radius, ), use_numeric_eigenstates=True, numeric_eigenstate_max_energy=10 * eV, numeric_eigenstate_max_angular_momentum=10, electric_potential_dc_correction=True, store_data_every=20, ) specs = [ ion.SphericalHarmonicSpecification( "cosine", electric_potential=cosine_pulse, **shared_kwargs ), ion.SphericalHarmonicSpecification( "sine", electric_potential=sine_pulse, **shared_kwargs ),
time_final=12 * pulse_width, ) ide_shared_kwargs = dict(evolution_method="RK4", time_step=1 * asec) msh_spec = ion.LineSpecification( "msh", time_step=1 * asec, x_bound=200 * bohr_radius, x_points=2**10, internal_potential=gaussian_well, initial_state=variational_ground_state, use_numeric_eigenstates=True, numeric_eigenstate_max_energy=20 * eV, analytic_eigenstate_type=ion.GaussianWellState, mask=ion.RadialCosineMask(inner_radius=175 * bohr_radius, outer_radius=200 * bohr_radius), animators=[ animation.animators.RectangleSplitLowerAnimator( postfix="__g2", axman_wavefunction=animation.animators.LineMeshAxis(), axman_lower_left=animation.animators. ElectricPotentialPlotAxis(show_vector_potential=False), axman_lower_right=animation.animators. WavefunctionStackplotAxis( states=[variational_ground_state]), fig_dpi_scale=1, target_dir=OUT_DIR, ) ], **shared_kwargs, )
fluence=flu, phase=cep, number_of_cycles=n_cycles, number_of_pulse_widths=3, window=ion.potentials.LogisticWindow( window_time=pulse_time_bound * pw, window_width=0.2 * pw), ) specs.append( ion.SphericalHarmonicSpecification( f"{pulse_type.__name__}__Nc={n_cycles}_pw={pw / asec:3f}as_flu={flu / Jcm2:3f}jcm2_cep={cep / pi:3f}pi__R={r_bound / bohr_radius:3f}br_ppbr={r_points_per_br}_L={l_bound}_dt={dt / asec:3f}as", r_bound=r_bound, r_points=r_points_per_br * r_bound / bohr_radius, l_bound=l_bound, time_step=dt, time_initial=-sim_time_bound * pw, time_final=(sim_time_bound + extra_end_time) * pw, mask=ion.RadialCosineMask(0.8 * r_bound, r_bound), electric_potential=pulse, electric_potential_dc_correction=True, use_numeric_eigenstates=True, numeric_eigenstate_max_energy=20 * eV, numeric_eigenstate_max_angular_momentum=20, checkpoints=True, checkpoint_dir=SIM_LIB, checkpoint_every=datetime.timedelta(minutes=1), store_radial_probability_current=True, )) si.utils.multi_map(run_spec, specs, processes=4)
t_init = 0 t_final = 1000 dt = 1 initial_state = ion.HydrogenBoundState( 1, 0, 0) + ion.HydrogenBoundState(2, 1, 0) window = ion.potentials.LinearRampTimeWindow(ramp_on_time=t_init * asec, ramp_time=200 * asec) e_field = ion.SineWave.from_frequency(1 / (50 * asec), amplitude=1 * atomic_electric_field, window=window) mask = ion.RadialCosineMask(inner_radius=(bound - 25) * bohr_radius, outer_radius=bound * bohr_radius) animators = [ src.ionization.animators.CylindricalSliceAnimator( postfix="_nm", target_dir=OUT_DIR, distance_unit="nm"), src.ionization.animators.CylindricalSliceAnimator( postfix="_br", target_dir=OUT_DIR, distance_unit="bohr_radius"), ] specs.append( ion.mesh.CylindricalSliceSpecification( "cyl_slice", time_initial=t_init * asec, time_final=t_final * asec, time_step=dt * asec, z_bound=20 * bohr_radius,
def compare_quasistatic_to_tdse(intensity, photon_energy): dummy = ion.SineWave.from_photon_energy(0.5 * eV) time_initial = 0 time_final = 8 * dummy.period_carrier time_front = 1 * dummy.period_carrier time_plateau = 5 * dummy.period_carrier efield = ion.SineWave.from_photon_energy_and_intensity( photon_energy, intensity) efield.window = ion.potentials.SmoothedTrapezoidalWindow( time_front=time_front, time_plateau=time_plateau) r_bound = 100 r_points = 4 * r_bound l_bound = 400 dt = 4 store = 5 h = hash(( intensity, photon_energy, time_initial, time_final, time_front, time_plateau, r_bound, r_points, l_bound, dt, store, )) title = f"P={intensity / atomic_intensity:5f}_E={photon_energy / eV:1f}_R={r_bound}_Rp={r_points}_L={l_bound}_dt={dt}_sde={store}" spec = ion.SphericalHarmonicSpecification( f"tdse_{h}", r_bound=r_bound * bohr_radius, r_points=r_points, l_bound=l_bound, internal_potential=ion.SoftCoulomb(softening_distance=0.05 * bohr_radius), time_initial=time_initial, time_final=time_final, time_step=dt * asec, electric_potential=efield, use_numeric_eigenstates=True, numeric_eigenstate_max_energy=20 * eV, numeric_eigenstate_max_angular_momentum=5, store_data_every=store, checkpoints=True, checkpoint_dir=SIM_LIB, checkpoint_every=50, mask=ion.RadialCosineMask(0.9 * r_bound * bohr_radius, r_bound * bohr_radius), ) sim = si.utils.find_or_init_sim(spec, search_dir=SIM_LIB) sim.info().log() if not sim.status == si.Status.FINISHED: sim.run_simulation(progress_bar=True) sim.info().log() sim.save(target_dir=SIM_LIB) sim.plot_wavefunction_vs_time(**PLOT_KWARGS) times = np.linspace(time_initial, time_final, 1e3) si.vis.xy_plot( title + "__efield_vs_time", times, efield.get_electric_field_amplitude(times), x_label=r"Time $t$", x_unit="asec", y_label=fr"$ {ion.vis.LATEX_EFIELD}(t) $)", y_unit="atomic_electric_field", **PLOT_KWARGS, ) tunneling_rate_vs_time = instantaneous_tunneling_rate( efield.get_electric_field_amplitude(times), sim.spec.initial_state.energy) si.vis.xy_plot( title + "__tunneling_rate_vs_time", times, tunneling_rate_vs_time * asec, x_label=r"Time $t$", x_unit="asec", y_label=r"Tunneling Rate ($\mathrm{as}^{-1}$)", **PLOT_KWARGS, ) wavefunction_remaining = np.empty_like(times) wavefunction_remaining[0] = 1 for ii, tunneling_rate in enumerate(tunneling_rate_vs_time[:-1]): wavefunction_remaining[ii + 1] = wavefunction_remaining[ii] * ( 1 - (tunneling_rate * np.abs(times[ii + 1] - times[ii]))) cycle_avg_rate = averaged_tunneling_rate(efield.amplitude) cycle_avg_norm_remaining_plat = np.exp(-cycle_avg_rate * time_plateau) cycle_avg_norm_remaining_all = np.exp(-cycle_avg_rate * (time_plateau + (2 * time_front))) for log in (True, False): si.vis.xxyy_plot( title + f"__comparison__log={log}", (sim.data_times, sim.data_times, sim.data_times, times), ( sim.norm_vs_time, sim.total_bound_state_overlap_vs_time, sim.state_overlaps_vs_time[sim.spec.initial_state], wavefunction_remaining, ), line_labels=( "TDSE Norm", "TDSE Bound States", "TDSE Initial State", "Tunneling", ), x_label=r"Time $t$", x_unit="fsec", y_label="Remaining Wavefunction", y_log_axis=log, hlines=[ cycle_avg_norm_remaining_plat, cycle_avg_norm_remaining_all ], hline_kwargs=[{ "linestyle": "--" }, { "linestyle": ":" }], **PLOT_KWARGS, )
if __name__ == "__main__": with si.utils.LogManager( "simulacra", "ionization", stdout_level=logging.INFO, file_logs=False, file_dir=OUT_DIR, file_level=logging.DEBUG, ) as logger: source = ion.potentials.SincPulse(pulse_width=200 * asec, fluence=1 * (J / (cm**2))) pulse_widths = [290, 310, 390, 410] # pulse_widths = [50, 100, 200, 400, 600, 800] t_step = 2 * asec mask = ion.RadialCosineMask(inner_radius=100 * bohr_radius, outer_radius=150 * bohr_radius) specs = [] for phase in ("cos", "sin"): for pw in pulse_widths: sinc = ion.potentials.SincPulse.from_amplitude_density( pulse_width=pw * asec, amplitude_density=source.amplitude_omega, phase=phase, ) specs.append( ion.SphericalHarmonicSpecification( "pw={}asec_phase={}".format(pw, phase), r_bound=150 * bohr_radius, r_points=600,
def make_plot(args): pulse_type, pw, flu, cep = args t_bound = T_BOUND_MAP[pulse_type] p_bound = P_BOUND_MAP[pulse_type] times = np.linspace(-t_bound * pw, t_bound * pw, 1e4) window = ion.potentials.LogisticWindow( window_time=p_bound * pw, window_width=0.2 * pw ) pulse = pulse_type(pulse_width=pw, fluence=flu, phase=cep, window=window) corrected_pulse = ion.DC_correct_electric_potential(pulse, times) efield = corrected_pulse.get_electric_field_amplitude(times) afield = corrected_pulse.get_vector_potential_amplitude_numeric_cumulative(times) starts = range(0, len(times), 50)[50:-50] sliced_times = list(times[start:] for start in starts) sliced_alphas = list( (proton_charge / electron_mass) * integ.cumtrapz( y=integ.cumtrapz(y=efield[start:], x=times[start:], initial=0), x=times[start:], initial=0, ) for start in starts ) identifier = f"{pulse_type.__name__}__pw={pw / asec:0f}as_flu={flu / Jcm2:2f}jcm2_cep={cep / pi:2f}pi" spec = ion.SphericalHarmonicSpecification( identifier, r_bound=250 * bohr_radius, r_points=250 * 4, l_bound=500, time_initial=times[0], time_final=times[-1], use_numeric_eigenstates=True, numeric_eigenstate_max_energy=10 * eV, numeric_eigenstate_max_angular_momentum=5, electric_potential=pulse, electric_potential_dc_correction=True, mask=ion.RadialCosineMask( inner_radius=225 * bohr_radius, outer_radius=250 * bohr_radius ), checkpoints=True, checkpoint_every=50, checkpoint_dir=SIM_LIB, ) sim = si.utils.find_or_init_sim(spec, search_dir=SIM_LIB) if sim.status != si.Status.FINISHED: sim.run_simulation() sim.save(target_dir=SIM_LIB) si.vis.xxyy_plot( identifier, [times, times, sim.times, *sliced_times], [ efield / atomic_electric_field, afield * (proton_charge / atomic_momentum), sim.radial_position_expectation_value_vs_time / bohr_radius, *(alpha / bohr_radius for alpha in sliced_alphas), ], line_labels=[ rf"$ {ion.vis.LATEX_EFIELD}(t) $", rf"$ e \, {ion.LATEX_AFIELD}(t) $", rf"$ \left\langle r(t) \right\rangle $", rf"$ \alpha(t) $", ], line_kwargs=[ None, None, None, *({"color": "black", "alpha": 0.5} for _ in starts), ], x_label=r"Time $t$", x_unit="asec", # y_label = r'Field Amplitude (a.u.) / Distance ($a_0$)', title=rf"$ \tau = {pw / asec:0f} \, \mathrm{{as}}, \; H = {flu / Jcm2:2f} \, \mathrm{{J/cm^2}}, \; \varphi = {cep / pi:2f}\pi $", **PLOT_KWARGS, )
spec_kwargs = dict( r_bound=r_bound * bohr_radius, r_points=r_bound * points_per_bohr_radius, l_bound=20, initial_state=ion.HydrogenBoundState(1, 0), time_initial=-t_bound * asec, time_final=(t_bound + t_extra) * asec, time_step=1 * asec, use_numeric_eigenstates=True, numeric_eigenstate_max_energy=10 * eV, numeric_eigenstate_max_angular_momentum=10, electric_potential=efield, electric_potential_dc_correction=True, mask=ion.RadialCosineMask( inner_radius=0.9 * r_bound * bohr_radius, outer_radius=r_bound * bohr_radius, ), store_data_every=10, snapshot_type=ion.SphericalHarmonicSnapshot, snapshot_times=[(t_bound + (n * 100)) * asec for n in range(100)], snapshot_kwargs=dict( plane_wave_overlap__max_wavenumber=60 * per_nm, plane_wave_overlap__wavenumber_points=200, plane_wave_overlap__theta_points=100, ), ) sim = ion.SphericalHarmonicSpecification( f"R={r_bound}_amp={amp}_phase={phase / pi:3f}pi_tB={t_bound}_tE={t_extra}", **spec_kwargs, ).to_sim()
FILE_NAME = os.path.splitext(os.path.basename(__file__))[0] OUT_DIR = os.path.join(os.getcwd(), "out", FILE_NAME) PLOT_KWARGS = dict(target_dir=OUT_DIR, img_format="png", fig_dpi_scale=6) if __name__ == "__main__": with si.utils.LogManager( "simulacra", "ionization", stdout_logs=True, stdout_level=logging.DEBUG, file_dir=OUT_DIR, file_logs=False, ) as logger: x = np.linspace(4.99, 5.01, 1e6) mask = ion.RadialCosineMask(inner_radius=2, outer_radius=5, smoothness=8) si.vis.xy_plot("mask_test", x, mask(r=x), **PLOT_KWARGS) # electric = ion.potentials.Rectangle(start_time = 25 * asec, end_time = 100 * asec, amplitude = 1 * atomic_electric_field) # mask = ion.RadialCosineMask(inner_radius = 40 * bohr_radius, outer_radius = 49 * bohr_radius) # sim = ion.SphericalHarmonicSpecification('mask', # time_final = 200 * asec, # r_bound = 50 * bohr_radius, r_points = 50 * 8, # l_bound = 100, # electric_potential = electric, # test_states = [ion.HydrogenBoundState(n, l) for n in range(6) for l in range(n)], # mask = mask).to_sim() # # sim.run_simulation() # sim.info().log()