def compute_inversion(dirname): print output.div_line print "computing population inversion" active_medium = create_medium(None) pump_system = model.pump.PumpSystem(params.pump_wavelen, params.pump_duration, params.pump_power, params.pump_efficiency) depop_model = create_depop_model(active_medium, params.depop_model_class) inv = params.inverter_class(active_medium, pump_system, depop_model) ref_inversion = inv.invert(params.inversion_rtol, params.inversion_min_count_t) rate_evals = (len(inv.inversion) - 1) * inv.evals_per_step pump_energy = params.pump_duration * params.pump_power stored_energy = model.energy.energy(params.lasing_wavelen, ref_inversion * active_medium.volume) if params.verbose: print "count_t:", len(inv.T) print "depopulation rate evaluation count:", rate_evals if params.inversion_validate: print "validating uniform ASE-induced depopulation rate approximation" ross_num_model = depop_model if isinstance(depop_model, model.depop.RossNumericalASEModel) else model.depop.RossNumericalASEModel(active_medium, params.depop_rate_rtol, params.depop_rate_min_samples) rate_rel_stddev = ross_num_model.rate_rel_stddev(ref_inversion) unitconv.print_result("depopulation rate rel. std. deviation [{}]: {}", ("%",), (rate_rel_stddev,)) if rate_rel_stddev > 10.0e-2: output.warn("uniform ASE-induced depopulation rate approximation is invalid") if isinstance(depop_model, model.depop.NumericalDepopulationModel): print "perturbing population inversion" perturb_depop_model = model.depop.PerturbedDepopulationModel(depop_model) perturb_inv = params.inverter_class(active_medium, pump_system, perturb_depop_model) perturb_ref_inversion = perturb_inv.invert(params.inversion_rtol, params.inversion_min_count_t) rel_error = model.error.perturbed_inversion_rel_error(ref_inversion, perturb_ref_inversion, params.inversion_rtol) else: rel_error = params.inversion_rtol gain_coef = ref_inversion * active_medium.doping_agent.xsection gain = math.exp(gain_coef * active_medium.length) ref_inversion_atol = ref_inversion * rel_error gain_atol = gain * (math.exp(ref_inversion_atol * active_medium.doping_agent.xsection * active_medium.length) - 1.0) stored_energy_atol = stored_energy * rel_error unitconv.print_result("pump energy [{}]: {}", ("mJ",), (pump_energy,)) unitconv.print_result("population inversion [{}]: {} ~ {}", ("cm^-3",), (ref_inversion, ref_inversion_atol)) unitconv.print_result("small signal gain: {} ~ {}", (), (gain, gain_atol)) unitconv.print_result("stored energy [{}]: {} ~ {}", ("mJ",), (stored_energy, stored_energy_atol)) if params.graphs: print output.status_writing dirname = output.init_dir(dirname) output.plot_inversion(dirname, inv) return ref_inversion, rel_error
def amplify_ref_pulse(dirname, num_types, counts, ref_inversion): print output.div_line print "amplifying ref. pulse" dirname = os.path.join(dirname, output.ref_pulse_rel_path) (int_type, amp_type), (_, _, count_z, count_t) = num_types, counts active_medium = create_medium(ref_inversion) input_beam = create_beam() rho, phi = input_beam.rho_ref, input_beam.phi_ref ref_pulse = create_pulse(active_medium, input_beam, rho, phi) integrator = model.integrator.DomainIntegrator(int_type) amp = amp_type(active_medium, count_z) num_density_out, _ = amp.amplify(rho, phi, ref_pulse, count_t) if active_medium.doping_agent.lower_lifetime in model.amplifier.ExactAmplifier.analytical_lower_lifetimes: exact_amp = model.amplifier.ExactOutputAmplifier(active_medium, count_z) exact_density_out, exact_population_final = exact_amp.amplify(rho, phi, ref_pulse, count_t) else: exact_density_out, exact_population_final = None, None fluence_out = integrator.integrate(amp.T, num_density_out) * active_medium.light_speed fluence_gain = fluence_out / input_beam.ref_fluence unitconv.print_result("fluence gain: {}", (), (fluence_gain,)) if params.graphs: count_z = len(amp.Z) fluences = np.empty(count_z) for l in range(count_z): fluences[l] = integrator.integrate(amp.T, amp.density[l]) * active_medium.light_speed print output.status_writing dirname = output.init_dir(dirname) output.plot_output(dirname, input_beam, ref_pulse, params.pulse_duration, amp, fluences, exact_density_out, exact_population_final)
def report_results(ref_inversion, max_output_fluence, output_photon_counts, output_energy, rel_gain_decrease, inversion_rel_error, rel_errors): print output.div_line print "results:" active_medium = create_medium(ref_inversion) energy_rel_error = model.error.energy_rel_error(active_medium, inversion_rel_error, rel_errors) pump_energy = params.pump_duration * params.pump_power stored_energy = model.energy.energy(params.lasing_wavelen, ref_inversion * active_medium.volume) input_beam = create_beam() input_photon_count = input_beam.fluence_integral(active_medium.radius) input_energy = model.energy.energy(params.lasing_wavelen, input_photon_count) input_energy *= params.train_pulse_count energy_gain = output_energy / input_energy added_energy = output_energy - input_energy extraction_eff = added_energy / stored_energy total_eff = added_energy / pump_energy stored_energy_abs_error = inversion_rel_error * stored_energy output_energy_abs_error = energy_rel_error * output_energy energy_gain_abs_error = energy_rel_error * energy_gain extraction_eff_abs_error = (added_energy + output_energy_abs_error) / max(stored_energy - stored_energy_abs_error, 0.0) - extraction_eff total_eff_abs_error = output_energy_abs_error / pump_energy max_output_fluence_abs_error = max_output_fluence * energy_rel_error photon_count_first, photon_count_last = output_photon_counts[0], output_photon_counts[-1] photon_count_first_abs_error, photon_count_last_abs_error = photon_count_first * energy_rel_error, photon_count_last * energy_rel_error rel_gain_decrease_abs_error = 0.0 if params.train_pulse_count > 1: rel_gain_decrease_abs_error = (photon_count_last + photon_count_last_abs_error) / max(photon_count_first - photon_count_first_abs_error, 0.0) - photon_count_last / photon_count_first unitconv.print_result("input energy [{}]: {}", ("mJ",), (input_energy,)) unitconv.print_result("output energy [{}]: {} ~ {}", ("mJ",), (output_energy, output_energy_abs_error)) unitconv.print_result("energy gain: {} ~ {}", (), (energy_gain, energy_gain_abs_error)) unitconv.print_result("extraction efficiency [{}]: {} ~ {}", ("%",), (extraction_eff, extraction_eff_abs_error)) unitconv.print_result("opt.-opt. efficiency [{}]: {} ~ {}", ("%",), (total_eff, total_eff_abs_error)) unitconv.print_result("max. output fluence [{}]: {} ~ {}", ("J/cm^2",), (max_output_fluence, max_output_fluence_abs_error)) unitconv.print_result("rel. gain decrease [{}]: {} ~ {}", ("%",), (rel_gain_decrease, rel_gain_decrease_abs_error))
def compare_depop_models(dirname): filename = lambda name: os.path.join(dirname, name) if not params.ext_depop_models: return print output.div_line print "comparing depopulation models" active_medium = core.create_medium(None) pump_system = model.pump.PumpSystem(params.pump_wavelen, params.pump_duration, params.pump_power, params.pump_efficiency) data = [] for depop_model_class in params.ext_depop_models: depop_model_label = depop_model_class.descr print depop_model_label depop_model = core.create_depop_model(active_medium, depop_model_class) inv = params.inverter_class(active_medium, pump_system, depop_model) inv.invert(params.inversion_rtol, params.inversion_min_count_t) depop_rate = np.vectorize(depop_model.rate)(inv.inversion) / active_medium.volume data.append((inv.T, inv.inversion, depop_rate, depop_model_class.descr, depop_model_class)) ref_inversion = inv.inversion[-1] unitconv.print_result("population inversion [{}]: {}", ("cm^-3",), (ref_inversion,)) unitconv.print_result("depopulation rate [{}]: {}", ("cm^-3 s^-1",), (depop_rate[-1],)) if params.graphs: print output.status_writing dirname = os.path.join(dirname, output.models_rel_path) dirname = output.init_dir(dirname) data.sort(key = lambda x: x[1][-1], reverse=True) Ts, inversions, depop_rates, labels, depop_model_classes = zip(*data) plot.plot_data(filename("inversions_evo"), "Population Inversion Evolution", (Ts, None, None, output.t_pump_label), (inversions, None, None, output.inversion_abs_label), labels) pump_rate = pump_system.effective_pump_rate / active_medium.volume abs_rate_ylim = None #(0.0, pump_rate * 1.25) non_zero_Ts = [T[1:] for T in Ts] non_zero_inversions = [inversion[1:] for inversion in inversions] non_zero_rates = [depop_rate[1:] for depop_rate in depop_rates] rel_depop_rates = [depop_rate / inversion for depop_rate, inversion in zip(non_zero_rates, non_zero_inversions)] plot.plot_data(filename("depop_rates"), "Depopulation Rate", (inversions, None, None, output.inversion_abs_label), (depop_rates, None, abs_rate_ylim, output.rate_label), labels, yvals=[(pump_rate, "pump rate")]) plot.plot_data(filename("depop_rates_alt"), "Depopulation Rate to Inversion Ratio", (non_zero_inversions, None, None, output.inversion_abs_label), (rel_depop_rates, None, None, output.rate_rel_label), labels) plot.plot_data(filename("depop_rates_evo"), "Depopulation Rate Evolution", (Ts, None, None, output.t_pump_label), (depop_rates, None, abs_rate_ylim, output.rate_label), labels, yvals=[(pump_rate, "pump rate")]) plot.plot_data(filename("depop_rates_alt_evo"), "Depopulation Rate to Inversion Ratio Evolution", (non_zero_Ts, None, None, output.t_pump_label), (rel_depop_rates, None, None, output.rate_rel_label), labels) if params.ext_alt_depop_model not in depop_model_classes: return alt_model_idx = depop_model_classes.index(params.ext_alt_depop_model) alt_T = Ts[alt_model_idx] alt_inversion = inversions[alt_model_idx] altinvs = [] aTs = [] altinv_inversion_rdiffs = [] for cls, T, inversion in zip(depop_model_classes, Ts, inversions): if cls is params.ext_alt_depop_model: continue uT = set(list(T) + list(alt_T)) aT = np.array(sorted(list(uT))) altinv = np.interp(aT, alt_T, alt_inversion)[1:] inv = np.interp(aT, T, inversion)[1:] rdiff = np.fabs(inv - altinv) / np.fmin(inv, altinv) aTs.append(aT[1:]) altinvs.append(altinv) altinv_inversion_rdiffs.append(rdiff) non_alt_labels = [label for i, label in enumerate(labels) if i != alt_model_idx] plot.plot_data(filename("inversions_rdiff_inv"), "Inversion Relative Difference", (altinvs, None, None, output.inversion_abs_label), (altinv_inversion_rdiffs, None, None, output.inversion_rdiff_label), non_alt_labels) plot.plot_data(filename("inversions_rdiff_evo"), "Inversion Relative Difference Evolution", (aTs, None, None, output.t_pump_label), (altinv_inversion_rdiffs, None, None, output.inversion_rdiff_label), non_alt_labels)
def compute_energy_geom_dependence(task_pool, dirname, inversions, constraints, num_types, counts): filename = lambda name: os.path.join(dirname, name) print output.div_line print "computing energy dependence on geometry parameters" min_medium_radius = params.ext_opt_geom_mediumradius[0] min_beam_radius = params.ext_opt_geom_beamradius[0] count_rm = params.ext_opt_geom_resolution[0] count_rb = params.ext_opt_geom_resolution[1] Rm = np.linspace(min_medium_radius, params.ext_opt_geom_mediumradius[1], count_rm) Rb = np.linspace(min_beam_radius, params.ext_opt_geom_beamradius[1], count_rb) inversions = np.meshgrid(inversions, Rb)[0].T stored_energies, input_energies, output_energies, rel_gain_decreases = task_pool.parallel_task(_energy_geom_dependence_task, (Rm, Rb), (inversions,), (num_types, counts)) output.show_status((count_rm, count_rb), params.extended_status_strides, True) pump_energy = params.pump_duration * params.pump_power energy_gains = output_energies / input_energies added_energies = output_energies - input_energies extraction_effs = added_energies / stored_energies total_effs = added_energies / pump_energy limits, comparisons = constraints price = lambda rm, rb: 1.0 / (rm * rb) optimum = optimize_output((Rm, Rb), output_energies, limits, comparisons, price) output_energy_optimum_params = (Rm[optimum[0]], Rb[optimum[1]]) if optimum else (None, None) unitconv.print_result("max. output energy [{}]: {}", ("mJ",), (output_energies[optimum] if optimum else None,)) unitconv.print_result("optimum geometry parameters (medium diameter [{}], beam diameter [{}]): ({}, {})", ("mm", "mm"), output_energy_optimum_params) optimum = optimize_output((Rm, Rb), energy_gains, limits, comparisons, price) energy_gain_optimum_params = (Rm[optimum[0]], Rb[optimum[1]]) if optimum else (None, None) unitconv.print_result("max. energy gain: {}", (), (energy_gains[optimum] if optimum else None,)) unitconv.print_result("optimum geometry parameters (medium diameter [{}], beam diameter [{}]): ({}, {})", ("mm", "mm"), energy_gain_optimum_params) optimum = optimize_output((Rm, Rb), extraction_effs, limits, comparisons, price) extraction_eff_optimum_params = (Rm[optimum[0]], Rb[optimum[1]]) if optimum else (None, None) unitconv.print_result("max. extraction efficiency [{}]: {}", ("%",), (extraction_effs[optimum] if optimum else None,)) unitconv.print_result("optimum geometry parameters (medium diameter [{}], beam diameter [{}]): ({}, {})", ("mm", "mm"), extraction_eff_optimum_params) optimum = optimize_output((Rm, Rb), total_effs, limits, comparisons, price) total_eff_optimum_params = (Rm[optimum[0]], Rb[optimum[1]]) if optimum else (None, None) unitconv.print_result("max. opt.-opt. efficiency [{}]: {}", ("%",), (total_effs[optimum] if optimum else None,)) unitconv.print_result("optimum geometry parameters (medium diameter [{}], beam diameter [{}]): ({}, {})", ("mm", "mm"), total_eff_optimum_params) optimum = optimize_output((Rm, Rb), -rel_gain_decreases, limits, comparisons, price) rel_gain_decrease_optimum_params = (Rm[optimum[0]], Rb[optimum[1]]) if optimum else (None, None) unitconv.print_result("min. rel. gain decrease [{}]: {}", ("%",), (rel_gain_decreases[optimum] if optimum else None,)) unitconv.print_result("optimum geometry parameters (medium diameter [{}], beam diameter [{}]): ({}, {})", ("mm", "mm"), rel_gain_decrease_optimum_params) if params.graphs: print output.status_writing extra_contours, xvals, yvals = limits dirname = os.path.join(dirname, output.opt_geom_rel_path) dirname = output.init_dir(dirname) plot.plot_color(filename("energy_in"), "Input Energy", (Rm, None, None, output.medium_radius_label), (Rb, None, None, output.beam_radius_label), (input_energies.T, None, output.energy_abs_pulse_label), params.out_num_auto_contours, extra_contours=extra_contours, xvals=xvals, yvals=yvals) plot.plot_color(filename("energy_out"), "Output Energy", (Rm, None, None, output.medium_radius_label), (Rb, None, None, output.beam_radius_label), (output_energies.T, None, output.energy_abs_pulse_label), params.out_num_auto_contours, extra_contours=extra_contours, xvals=xvals, yvals=yvals) plot.plot_color(filename("energy_gain"), "Energy Gain", (Rm, None, None, output.medium_radius_label), (Rb, None, None, output.beam_radius_label), (energy_gains.T, None, output.energy_rel_label), params.out_num_auto_contours, extra_contours=extra_contours, xvals=xvals, yvals=yvals) plot.plot_color(filename("efficiency_extr"), "Extraction Efficiency", (Rm, None, None, output.medium_radius_label), (Rb, None, None, output.beam_radius_label), (extraction_effs.T, None, output.extraction_eff_label), params.out_num_auto_contours, extra_contours=extra_contours, xvals=xvals, yvals=yvals) plot.plot_color(filename("efficiency_opt2"), "Optical to Optical Efficiency", (Rm, None, None, output.medium_radius_label), (Rb, None, None, output.beam_radius_label), (total_effs.T, None, output.total_eff_label), params.out_num_auto_contours, extra_contours=extra_contours, xvals=xvals, yvals=yvals) if params.train_pulse_count > 1: plot.plot_color(filename("gain_decrease"), "Gain Decrease", (Rm, None, None, output.medium_radius_label), (Rb, None, None, output.beam_radius_label), (rel_gain_decreases.T, None, output.rel_gain_decrease_label), params.out_num_auto_contours, extra_contours=extra_contours, xvals=xvals, yvals=yvals)
def compute_energy_pump_dependence(task_pool, dirname, inversions, constraints, num_types, counts): filename = lambda name: os.path.join(dirname, name) print output.div_line print "computing energy dependence on pumping parameters" active_medium = core.create_medium(None) input_beam = core.create_beam() input_photon_count = input_beam.fluence_integral(active_medium.radius) input_energy = model.energy.energy(params.lasing_wavelen, input_photon_count) input_energy *= params.train_pulse_count count_tau = params.ext_opt_pump_resolution[0] count_pwr = params.ext_opt_pump_resolution[1] Tau = np.linspace(params.ext_opt_pump_duration[0], params.ext_opt_pump_duration[1], count_tau) Pwr = np.linspace(params.ext_opt_pump_power[0], params.ext_opt_pump_power[1], count_pwr) output_energies, rel_gain_decreases = task_pool.parallel_task(_energy_pump_dependence_task, (Tau, Pwr), (inversions,), (num_types, counts)) output.show_status((count_tau, count_pwr), params.extended_status_strides, True) pump_energies = np.prod(np.array(np.meshgrid(Tau, Pwr)), axis=0).T stored_energies = model.energy.energy(params.lasing_wavelen, inversions * active_medium.volume) energy_gains = output_energies / input_energy added_energies = output_energies - input_energy extraction_effs = added_energies / stored_energies total_effs = added_energies / pump_energies limits, comparisons = constraints price = lambda tau, pwr: tau * pwr unitconv.print_result("input energy [{}]: {}", ("mJ",), (input_energy,)) optimum = optimize_output((Tau, Pwr), output_energies, limits, comparisons, price) output_energy_optimum_params = (Tau[optimum[0]], Pwr[optimum[1]]) if optimum else (None, None) unitconv.print_result("max. output energy [{}]: {}", ("mJ",), (output_energies[optimum] if optimum else None,)) unitconv.print_result("optimum pumping parameters (duration [{}], power [{}]): ({}, {})", ("us", "W"), output_energy_optimum_params) optimum = optimize_output((Tau, Pwr), energy_gains, limits, comparisons, price) energy_gain_optimum_params = (Tau[optimum[0]], Pwr[optimum[1]]) if optimum else (None, None) unitconv.print_result("max. energy gain: {}", (), (energy_gains[optimum] if optimum else None,)) unitconv.print_result("optimum pumping parameters (duration [{}], power [{}]): ({}, {})", ("us", "W"), energy_gain_optimum_params) optimum = optimize_output((Tau, Pwr), extraction_effs, limits, comparisons, price) extraction_eff_optimum_params = (Tau[optimum[0]], Pwr[optimum[1]]) if optimum else (None, None) unitconv.print_result("max. extraction efficiency [{}]: {}", ("%",), (extraction_effs[optimum] if optimum else None,)) unitconv.print_result("optimum pumping parameters (duration [{}], power [{}]): ({}, {})", ("us", "W"), extraction_eff_optimum_params) optimum = optimize_output((Tau, Pwr), total_effs, limits, comparisons, price) total_eff_optimum_params = (Tau[optimum[0]], Pwr[optimum[1]]) if optimum else (None, None) unitconv.print_result("max. opt.-opt. efficiency [{}]: {}", ("%",), (total_effs[optimum] if optimum else None,)) unitconv.print_result("optimum pumping parameters (duration [{}], power [{}]): ({}, {})", ("us", "W"), total_eff_optimum_params) optimum = optimize_output((Tau, Pwr), -rel_gain_decreases, limits, comparisons, price) rel_gain_decrease_optimum_params = (Tau[optimum[0]], Pwr[optimum[1]]) if optimum else (None, None) unitconv.print_result("min. rel. gain decrease [{}]: {}", ("%",), (rel_gain_decreases[optimum] if optimum else None,)) unitconv.print_result("optimum pumping parameters (duration [{}], power [{}]): ({}, {})", ("us", "W"), rel_gain_decrease_optimum_params) if params.graphs: print output.status_writing extra_contours, xvals, yvals = limits dirname = os.path.join(dirname, output.opt_pump_rel_path) graph_types = [ (dirname, Pwr, output.pump_power_label), (os.path.join(dirname, output.alt_plot_rel_path), Pwr * params.pump_efficiency / active_medium.volume, output.eff_power_density_label), ] for dirname, Y, ylabel in graph_types: dirname = output.init_dir(dirname) plot.plot_color(filename("energy_out"), "Output Energy", (Tau, None, None, output.pump_duration_label), (Y, None, None, ylabel), (output_energies.T, None, output.energy_abs_pulse_label), params.out_num_auto_contours, extra_contours=extra_contours, xvals=xvals, yvals=yvals) plot.plot_color(filename("energy_gain"), "Energy Gain", (Tau, None, None, output.pump_duration_label), (Y, None, None, ylabel), (energy_gains.T, None, output.energy_rel_label), params.out_num_auto_contours, extra_contours=extra_contours, xvals=xvals, yvals=yvals) plot.plot_color(filename("efficiency_extr"), "Extraction Efficiency", (Tau, None, None, output.pump_duration_label), (Y, None, None, ylabel), (extraction_effs.T, None, output.extraction_eff_label), params.out_num_auto_contours, extra_contours=extra_contours, xvals=xvals, yvals=yvals) plot.plot_color(filename("efficiency_opt2"), "Optical to Optical Efficiency", (Tau, None, None, output.pump_duration_label), (Y, None, None, ylabel), (total_effs.T, None, output.total_eff_label), params.out_num_auto_contours, extra_contours=extra_contours, xvals=xvals, yvals=yvals) if params.train_pulse_count > 1: plot.plot_color(filename("gain_decrease"), "Gain Decrease", (Tau, None, None, output.pump_duration_label), (Y, None, None, ylabel), (rel_gain_decreases.T, None, output.rel_gain_decrease_label), params.out_num_auto_contours, extra_contours=extra_contours, xvals=xvals, yvals=yvals)
ref_pulse = core.create_pulse(active_medium, input_beam, input_beam.rho_ref, input_beam.phi_ref) (int_type, amp_type), (_, _, count_z, count_t) = num_types, counts integrator = model.integrator.DomainIntegrator(int_type) amp = amp_type(active_medium, count_z) amp_3 = model.amplifier.ExactOutputAmplifier(active_medium_3, count_z) amp_4 = model.amplifier.ExactOutputAmplifier(active_medium_4, count_z) amplify_args = (input_beam.rho_ref, input_beam.phi_ref, ref_pulse, count_t) print "zero" density_out_4, _ = amp_4.amplify(*amplify_args) fluence_out_4 = integrator.integrate(amp_4.T, density_out_4) * active_medium_4.light_speed fluence_gain_4 = fluence_out_4 / input_beam.ref_fluence unitconv.print_result("fluence gain: {}", (), (fluence_gain_4,)) lsl_output_label = "finite" if lower_lifetime == 0.0: lsl_output_label = "zero" elif math.isinf(lower_lifetime): lsl_output_label = "infinite" print lsl_output_label density_out, _ = amp.amplify(*amplify_args) fluence_out = integrator.integrate(amp.T, density_out) * active_medium.light_speed fluence_gain = fluence_out / input_beam.ref_fluence unitconv.print_result("fluence gain: {}", (), (fluence_gain,)) print "infinite" density_out_3, _ = amp_3.amplify(*amplify_args) fluence_out_3 = integrator.integrate(amp_3.T, density_out_3) * active_medium_3.light_speed