inital commit
This commit is contained in:
commit
6c54c16f87
1
bachelorarbeit/.gitignore
vendored
Normal file
1
bachelorarbeit/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
3934
bachelorarbeit/Cargo.lock
generated
Normal file
3934
bachelorarbeit/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
22
bachelorarbeit/Cargo.toml
Normal file
22
bachelorarbeit/Cargo.toml
Normal file
@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "bachelorarbeit"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
gauss-quad = "0.1.8"
|
||||
num = "0.4.2"
|
||||
egui = "0.27.2"
|
||||
egui_extras = "0.27.2"
|
||||
eframe = "0.27.2"
|
||||
egui_plot = "0.27.2"
|
||||
indicatif = "0.17.8"
|
||||
nohash-hasher = "0.2.0"
|
||||
|
||||
|
||||
[profile.release]
|
||||
debug = true
|
||||
# lto = "fat"
|
||||
# codegen-units = 1
|
491
bachelorarbeit/flamegraph.svg
Normal file
491
bachelorarbeit/flamegraph.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 79 KiB |
491
bachelorarbeit/flamegraph_btreemap.svg
Normal file
491
bachelorarbeit/flamegraph_btreemap.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 79 KiB |
491
bachelorarbeit/flamegraph_hasmap.svg
Normal file
491
bachelorarbeit/flamegraph_hasmap.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 104 KiB |
BIN
bachelorarbeit/gauss_quad_lut.morello
Normal file
BIN
bachelorarbeit/gauss_quad_lut.morello
Normal file
Binary file not shown.
BIN
bachelorarbeit/perf.data
Normal file
BIN
bachelorarbeit/perf.data
Normal file
Binary file not shown.
BIN
bachelorarbeit/perf.data.old
Normal file
BIN
bachelorarbeit/perf.data.old
Normal file
Binary file not shown.
221
bachelorarbeit/src/calc.rs
Normal file
221
bachelorarbeit/src/calc.rs
Normal file
@ -0,0 +1,221 @@
|
||||
use core::f64::consts::PI;
|
||||
use gauss_quad::GaussLegendre;
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::gq_storage; // This should be moved to main.rs after new archtitecture (see main.rs TODO)
|
||||
|
||||
pub type Complex = num::complex::Complex<f64>;
|
||||
|
||||
const M_ROH: f64 = 0.7736;
|
||||
const M_PI: f64 = 0.13957;
|
||||
pub const S0: f64 = 4.0 * M_PI * M_PI;
|
||||
const M_K: f64 = 0.496;
|
||||
const B0: f64 = 1.055;
|
||||
const B1: f64 = 0.15;
|
||||
const LAMBDA1: f64 = 1.57;
|
||||
const LAMBDA2: f64 = -1.96;
|
||||
const LAMBDA_HIGH: f64 = 10.0;
|
||||
pub const EPSILON: f64 = 1e-15;
|
||||
const S_MID_CUTOFF: f64 = 1.42 * 1.42;
|
||||
const INF: f64 = 1e5;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Cache {
|
||||
pub gauss_quad_lut: HashMap<u32, (Rc<[f64]>, Rc<[f64]>), nohash_hasher::BuildNoHashHasher<u32>>,
|
||||
pub delta_lut: HashMap<u64, f64, nohash_hasher::BuildNoHashHasher<u64>>,
|
||||
pub omnes_lut: HashMap<u32, HashMap<u64, Complex, nohash_hasher::BuildNoHashHasher<u64>>, nohash_hasher::BuildNoHashHasher<u32>> // First key is n, second is s
|
||||
}
|
||||
|
||||
impl Cache {
|
||||
pub fn from_file(filepath: &str) -> io::Result<Cache> {
|
||||
let me = Cache{
|
||||
gauss_quad_lut: gq_storage::deserialize(filepath, |_| true)?.into_iter()
|
||||
.map(|(roots, weights)| (u32::try_from(roots.len()).unwrap(), (Rc::from(roots), Rc::from(weights)))).collect(),
|
||||
delta_lut: HashMap::with_hasher(Default::default()),
|
||||
omnes_lut: HashMap::with_hasher(Default::default())
|
||||
};
|
||||
Ok(me)
|
||||
}
|
||||
}
|
||||
|
||||
// derivated values
|
||||
|
||||
fn lambda_0() -> f64 {
|
||||
delta((2.0*M_K).powi(2))
|
||||
}
|
||||
|
||||
fn delta_mid_cutoff() -> f64 {
|
||||
delta(S_MID_CUTOFF)
|
||||
}
|
||||
|
||||
fn atan_shift(x: f64) -> f64 {
|
||||
let atan_std: f64 = x.atan();
|
||||
if atan_std < 0.0 {
|
||||
atan_std + PI
|
||||
} else {
|
||||
atan_std
|
||||
}
|
||||
}
|
||||
|
||||
fn integrate<G:FnMut(f64) -> f64>(roots: &[f64], weights: &[f64], a:f64, b:f64, mut f: G) -> f64 {
|
||||
let mut sum: f64 = 0.0;
|
||||
let mut i: usize = 0;
|
||||
if roots.len() != weights.len() {
|
||||
panic!("Error: roots and weights are of different length");
|
||||
}
|
||||
|
||||
while i < roots.len() {
|
||||
sum += weights[i] * f(roots[i]*(b-a)/2.0 + (a+b)/2.0);
|
||||
i += 1;
|
||||
}
|
||||
sum * (b-a)/2.0
|
||||
}
|
||||
|
||||
fn integrate_complex<G:FnMut(f64) -> Complex>(roots: &[f64], weights: &[f64], a:f64, b:f64, mut f: G) -> Complex {
|
||||
let mut sum: Complex = Complex::new(0.0,0.0);
|
||||
let mut i: usize = 0;
|
||||
if roots.len() != weights.len() {
|
||||
panic!("Error: roots and weights are of different length");
|
||||
}
|
||||
while i < roots.len() {
|
||||
sum += weights[i] * f(roots[i]*(b-a)/2.0 + (a+b)/2.0);
|
||||
i += 1;
|
||||
}
|
||||
sum * (b-a)/2.0
|
||||
}
|
||||
|
||||
fn omega(s: f64) -> f64 {
|
||||
let a = s.sqrt();
|
||||
let b = (1.05f64.powi(2) - s).sqrt();
|
||||
(a - b) / (a + b)
|
||||
}
|
||||
|
||||
fn k(s: f64) -> f64 {
|
||||
(s/4.0 - M_PI.powi(2)).sqrt()
|
||||
}
|
||||
|
||||
pub fn delta_with_lut(cache:&mut Cache, s: f64) -> f64 {
|
||||
match cache.delta_lut.get(&s.to_bits()) {
|
||||
Some(val) => {
|
||||
*val
|
||||
}
|
||||
None => {
|
||||
let val = delta(s);
|
||||
cache.delta_lut.insert(s.to_bits(), val);
|
||||
val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delta(s: f64) -> f64 {
|
||||
if s <= 2.0 * M_K {
|
||||
atan_shift(
|
||||
(s.sqrt() / (2.0*k(s).powi(3))
|
||||
* (M_ROH.powi(2) - s)
|
||||
* ( (2.0*M_PI.powi(3)) / (M_ROH.powi(2) * s.sqrt()) + B0 + B1 * omega(s))
|
||||
).powi(-1)
|
||||
)
|
||||
} else if s <= S_MID_CUTOFF {
|
||||
let par = 0.5 * s.sqrt() / M_K - 1.0;
|
||||
lambda_0() + LAMBDA1 * par + LAMBDA2 * par.powi(2)
|
||||
} else {
|
||||
PI +
|
||||
(delta_mid_cutoff() - PI)
|
||||
* (LAMBDA_HIGH * LAMBDA_HIGH + S_MID_CUTOFF)
|
||||
/ (LAMBDA_HIGH * LAMBDA_HIGH + s)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn omnes_integrand_tan(cache:&mut Cache, s_tick:f64, s:f64) -> Complex {
|
||||
let sub = s_tick.tan();
|
||||
(delta_with_lut(cache, sub) - delta_with_lut(cache, s))
|
||||
/ (
|
||||
sub
|
||||
* (sub - s + Complex::new(0.0, EPSILON))
|
||||
* s_tick.cos().powi(2)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn omnes_integrand(cache:&mut Cache, s_tick:f64, s:f64) -> Complex {
|
||||
(delta_with_lut(cache, s_tick) - delta_with_lut(cache, s))
|
||||
/ (s_tick * (s_tick - s + Complex::new(0.0, EPSILON)))
|
||||
}
|
||||
|
||||
pub fn omnes(cache:&mut Cache, s:f64, n:u32, use_tan: bool) -> Complex {
|
||||
let roots: Rc<[f64]>;
|
||||
let weights: Rc<[f64]>;
|
||||
|
||||
if let Some(inner_lut) = cache.omnes_lut.get(&n) {
|
||||
if let Some(res) = inner_lut.get(&s.to_bits()) {
|
||||
return *res
|
||||
}
|
||||
}
|
||||
|
||||
if !cache.omnes_lut.contains_key(&n) {
|
||||
cache.omnes_lut.insert(n, HashMap::with_hasher(Default::default()));
|
||||
}
|
||||
|
||||
match cache.gauss_quad_lut.get_mut(&n) {
|
||||
Some(gq_values) => {
|
||||
roots = Rc::clone(&gq_values.0);
|
||||
weights = Rc::clone(&gq_values.1);
|
||||
}
|
||||
None => {
|
||||
let gq_values = GaussLegendre::nodes_and_weights(n.try_into().unwrap());
|
||||
roots = Rc::from(gq_values.0.as_slice());
|
||||
weights = Rc::from(gq_values.1.as_slice());
|
||||
}
|
||||
}
|
||||
|
||||
if !cache.gauss_quad_lut.contains_key(&n) {
|
||||
let gq_values = GaussLegendre::nodes_and_weights(n.try_into().unwrap());
|
||||
cache.gauss_quad_lut.insert(n, (Rc::from(gq_values.0), Rc::from(gq_values.1)));
|
||||
println!("n_omnes={} is not included in the lookup file. Consider generating a new lookup file via the appropriate function in gq_storage.rs", n);
|
||||
}
|
||||
|
||||
let intgrl = if use_tan {
|
||||
integrate_complex(&roots, &weights, S0.atan(), PI / 2.0, |s_tick| omnes_integrand_tan(cache, s_tick, s))
|
||||
} else {
|
||||
integrate_complex(&roots, &weights, S0, INF, |s_tick| omnes_integrand(cache, s_tick, s))
|
||||
};
|
||||
let omnes_res = (s/PI*(intgrl)).exp() * (S0 / Complex::new(S0 - s, -EPSILON)).powf(delta_with_lut(cache, s) / PI);
|
||||
//cache.omnes_lut.get_mut(&n).unwrap().insert(s.to_bits(), omnes_res);
|
||||
println!("{:?}", omnes_res);
|
||||
omnes_res
|
||||
}
|
||||
|
||||
pub fn phi0_integrand(cache:&mut Cache, x: f64, s: f64, n_omnes:u32, use_tan_omnes: bool) -> f64 {
|
||||
let x_sub = x.tan().powi(2) + S0;
|
||||
let omnes_s = omnes(cache, s, n_omnes, use_tan_omnes);
|
||||
let omnes_x = omnes(cache, x_sub, n_omnes, use_tan_omnes);
|
||||
(omnes_x / omnes_s).norm_sqr().ln()
|
||||
/ ( (x_sub)* (x_sub-s) )
|
||||
/ x.cos().powi(2) // Don't use x_sub here, since this term is from tan substitution itself
|
||||
}
|
||||
|
||||
pub fn phi0(cache:&mut Cache, s: f64, n_omnes: u32, n_phi0: u32, use_tan_omnes: bool, use_tan_phi0: bool, use_xsub: bool) -> f64 {
|
||||
if !cache.gauss_quad_lut.contains_key(&n_phi0) {
|
||||
let gq_values = GaussLegendre::nodes_and_weights(n_phi0.try_into().unwrap());
|
||||
cache.gauss_quad_lut.insert(n_phi0, (Rc::from(gq_values.0), Rc::from(gq_values.1)));
|
||||
println!("n_omnes={} is not included in the lookup file. Consider generating a new lookup file via the appropriate function in gq_storage.rs", n_phi0);
|
||||
}
|
||||
let (ref roots, ref weights) = cache.gauss_quad_lut.get(&n_phi0).unwrap();
|
||||
let (roots, weights) = (Rc::clone(roots), Rc::clone(weights));
|
||||
|
||||
let analyt = omnes(cache, s, n_omnes, use_tan_omnes).norm_sqr().ln() / S0.sqrt() / 2.0;
|
||||
let intgrl = s / PI * integrate(&*roots, &*weights, 0.0, PI / 2.0, |x| phi0_integrand(cache,x,s,n_omnes, use_tan_omnes));
|
||||
-(s-S0).sqrt() * (intgrl - analyt)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn bit_pattern_randomness_tester(a:f64, b:f64, n_points: u64) -> Vec<f64>{
|
||||
let mut modulos = vec![0.0; n_points as usize];
|
||||
let x_values: Vec<u64> = (0..modulos.len() as u32).map(|x| (f64::from(x) * ((b - a) / f64::from(modulos.len() as u32)) + a).to_bits()).collect();
|
||||
for i in 0..x_values.len() {
|
||||
let val = (x_values[i] % n_points) as usize;
|
||||
modulos[val] += 1.0;
|
||||
}
|
||||
modulos
|
||||
}
|
84
bachelorarbeit/src/gq_storage.rs
Normal file
84
bachelorarbeit/src/gq_storage.rs
Normal file
@ -0,0 +1,84 @@
|
||||
//! This module writes and reads roots and weights of gauss-quad into files, using a dedicated file format.
|
||||
//! The format works as follows: One u64 is written, indicating the n of the roots and weights that follow
|
||||
//! (thereby hinting at the number of floats that are following before the next u64, which is 2*n). This is repeated for
|
||||
//! arbitrary n.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{self, BufReader, BufWriter, Read, Write, Seek, SeekFrom},
|
||||
};
|
||||
|
||||
use gauss_quad::GaussLegendre;
|
||||
|
||||
/// Writes roots and weights of gauss-quad into a file at `filepath`. params contains roots and weights for multiple n.
|
||||
pub fn serialize(filepath: &str, params: Vec<(Vec<f64>, Vec<f64>)>) -> io::Result<()> {
|
||||
let file = File::create(filepath)?;
|
||||
let mut file = BufWriter::new(file);
|
||||
for (roots, weights) in params.iter() {
|
||||
file.write_all(&u64::try_from(roots.len()).unwrap().to_le_bytes())?;
|
||||
for root in roots {
|
||||
file.write_all(&root.to_bits().to_le_bytes())?;
|
||||
}
|
||||
for weight in weights {
|
||||
file.write_all(&weight.to_bits().to_le_bytes())?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn deserialize(filepath: &str, filter: impl Fn(u64) -> bool) -> io::Result<Vec<(Vec<f64>, Vec<f64>)>> {
|
||||
let file = File::open(filepath)?;
|
||||
let mut file = BufReader::new(file);
|
||||
let mut buf = [0u8; 8];
|
||||
|
||||
let mut values = Vec::new();
|
||||
|
||||
'outer: loop {
|
||||
let res = file.read(&mut buf)?;
|
||||
if res < 8 {
|
||||
break;
|
||||
}
|
||||
let n = u64::from_le_bytes(buf);
|
||||
|
||||
// skips stored floats for n that should not be stored
|
||||
if !filter(n) {
|
||||
file.seek(SeekFrom::Current(i64::try_from(2*n*8).unwrap())).unwrap();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Stores roots and weights into values Vec
|
||||
|
||||
let mut roots = Vec::new();
|
||||
for _ in 0..n {
|
||||
let res = file.read(&mut buf)?;
|
||||
if res < 8 {
|
||||
break 'outer;
|
||||
}
|
||||
roots.push(f64::from_bits(u64::from_le_bytes(buf)));
|
||||
}
|
||||
|
||||
let mut weights = Vec::new();
|
||||
for _ in 0..n {
|
||||
let res = file.read(&mut buf)?;
|
||||
if res < 8 {
|
||||
break 'outer;
|
||||
}
|
||||
weights.push(f64::from_bits(u64::from_le_bytes(buf)));
|
||||
}
|
||||
values.push((roots, weights));
|
||||
}
|
||||
Ok(values)
|
||||
}
|
||||
|
||||
pub fn fill_with_gauss_quad(n_values: Vec<u64>) {
|
||||
let mut params = Vec::new();
|
||||
for i in n_values {
|
||||
let gq = GaussLegendre::init(usize::try_from(i).unwrap());
|
||||
params.push((gq.nodes, gq.weights));
|
||||
}
|
||||
serialize("./gauss_quad_lut.morello", params).unwrap();
|
||||
let res = deserialize("./gauss_quad_lut.morello", |_| true);
|
||||
println!("{:?}", res);
|
||||
}
|
247
bachelorarbeit/src/main.rs
Normal file
247
bachelorarbeit/src/main.rs
Normal file
@ -0,0 +1,247 @@
|
||||
|
||||
// TODO
|
||||
// - Lookup Table implementieren -> Weights, roots schon früher rausziehen?
|
||||
// -> Warum macht delta_lut alles langsamer?
|
||||
// - Omnes auch komplex integrieren (geht nicht mit Integralmethode von gauss-quad)
|
||||
// - Textfelder und "Berechnen"-Button in UI, um z.B. Wertebereich zu setzen
|
||||
// - Neue Architketur: struct calculator, das lookups speichert -> In die nötigen Funktionen übergeben. Dadurch kann man omnes auch als single calc machen und trotzdem die Punkte nur einmal berechnen
|
||||
// - AutoImport ausschalten
|
||||
|
||||
|
||||
use egui_plot::{log_grid_spacer, AxisHints, GridInput, GridMark, Legend, Line, Plot};
|
||||
use num::complex::ComplexFloat;
|
||||
use std::time::Instant;
|
||||
|
||||
mod gq_storage;
|
||||
mod calc;
|
||||
|
||||
struct App {
|
||||
plot_data: Vec<PlotCurve>,
|
||||
plots_available: [String; 6],
|
||||
calc_cache: calc::Cache,
|
||||
scaling_type: ScalingType,
|
||||
a: f64,
|
||||
b: f64,
|
||||
n_points: u32,
|
||||
n_omnes: u32,
|
||||
n_phi0: u32,
|
||||
use_tan_omnes: bool,
|
||||
use_tan_phi0: bool,
|
||||
use_xsub_phi0: bool
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct PlotCurve {
|
||||
points: Vec<[f64;2]>,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl Default for App {
|
||||
fn default() -> Self {
|
||||
App {
|
||||
plot_data: Vec::default(),
|
||||
plots_available: ["Delta".to_string(), "Omnes Integrand".to_string(), "Omnes".to_string(), "Phi0 Integrand".to_string(), "Phi0".to_string(), "Prozentueller Fehler".to_string()],
|
||||
calc_cache: calc::Cache::default(),
|
||||
scaling_type: ScalingType::default(),
|
||||
a: calc::S0,
|
||||
b: 9.0,
|
||||
n_points: 5000,
|
||||
n_omnes:1000,
|
||||
n_phi0:1000,
|
||||
use_tan_omnes: true,
|
||||
use_tan_phi0: true,
|
||||
use_xsub_phi0: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Clone, Copy)]
|
||||
enum ScalingType {
|
||||
Logarithmic,
|
||||
#[default]
|
||||
Linear
|
||||
}
|
||||
|
||||
impl eframe::App for App {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
let cur_scaling_type = self.scaling_type;
|
||||
egui::ComboBox::from_label("pick y-scaling").selected_text(format!("{:?}", self.scaling_type)).show_ui(ui, |ui| {
|
||||
ui.selectable_value(&mut self.scaling_type, ScalingType::Logarithmic, "log10");
|
||||
ui.selectable_value(&mut self.scaling_type, ScalingType::Linear, "linear");
|
||||
});
|
||||
|
||||
float_text_edit_singleline(ui, &mut self.a);
|
||||
float_text_edit_singleline(ui, &mut self.b);
|
||||
int_text_edit_singleline(ui, &mut self.n_points);
|
||||
int_text_edit_singleline(ui, &mut self.n_omnes);
|
||||
int_text_edit_singleline(ui, &mut self.n_phi0);
|
||||
|
||||
ui.checkbox(&mut self.use_tan_omnes, "Use tan()-subst. for Omnes");
|
||||
ui.checkbox(&mut self.use_tan_phi0, "Use tan()-subst. for Phi0");
|
||||
ui.checkbox(&mut self.use_xsub_phi0, "Use second subst. for Phi0");
|
||||
|
||||
let button_clear = ui.button("Clear canvas");
|
||||
if button_clear.clicked() {
|
||||
self.plot_data = Vec::new();
|
||||
}
|
||||
|
||||
for i in 0..self.plots_available.len() {
|
||||
let button = ui.button( format!("Calculate {}", self.plots_available[i].clone()));
|
||||
if button.clicked() {
|
||||
let x_values: Vec<f64> = (0..self.n_points).map(|x| -> f64 {f64::from(x) * ((self.b - self.a) / f64::from(self.n_points)) + self.a}).collect();
|
||||
match i {
|
||||
0 => {
|
||||
let y_values_delta:Vec<f64> = x_values.iter().map(|&x| calc::delta_with_lut(&mut self.calc_cache, x)).collect();
|
||||
self.plot_data.push(PlotCurve {
|
||||
points: x_values.iter().zip(y_values_delta.iter()).map(|(&x,&y)| [x.powf(0.5),y]).collect(),
|
||||
name: "Delta".to_string()
|
||||
})
|
||||
}
|
||||
1 => {
|
||||
let y_values_omnes_integrand: Vec<f64> = x_values.iter().map(|&x| calc::omnes_integrand(&mut self.calc_cache, x, 100.0).abs()).collect();
|
||||
self.plot_data.push(PlotCurve {
|
||||
points: x_values.iter().zip(y_values_omnes_integrand.iter()).map(|(&x,&y)| [x.powf(0.5),y]).collect(),
|
||||
name: "Omnes Integrand".to_string()
|
||||
})
|
||||
}
|
||||
2 => {
|
||||
let y_values_omnes: Vec<f64> = x_values.iter().map(|&x| calc::omnes(&mut self.calc_cache, x, self.n_omnes, self.use_tan_omnes).abs().powi(2)).collect();
|
||||
self.plot_data.push(PlotCurve {
|
||||
points: x_values.iter().zip(y_values_omnes.iter()).map(|(&x,&y)| [x.powf(0.5),y]).collect(),
|
||||
name: "Omnes".to_string()
|
||||
})
|
||||
}
|
||||
3 => {
|
||||
let y_values_phi0_integrand: Vec<f64> = x_values.iter().map(|&x| calc::phi0_integrand(&mut self.calc_cache, x, 10000.0, self.n_omnes, self.use_tan_omnes)).collect();
|
||||
self.plot_data.push(PlotCurve {
|
||||
points: x_values.iter().zip(y_values_phi0_integrand.iter()).map(|(&x,&y)| [x.powf(0.5),y]).collect(),
|
||||
name: "Phi0 Integrand".to_string()
|
||||
})
|
||||
}
|
||||
4 => {
|
||||
let t0 = Instant::now();
|
||||
let y_values_phi0: Vec<f64> = x_values.iter().map(|&x| calc::phi0(&mut self.calc_cache, x, self.n_omnes, self.n_phi0, self.use_tan_omnes, self.use_tan_phi0, self.use_xsub_phi0)).collect();
|
||||
println!("{:?}", t0.elapsed());
|
||||
self.plot_data.push(PlotCurve {
|
||||
points: x_values.iter().zip(y_values_phi0.iter()).map(|(&x,&y)| [x.powf(0.5),y]).collect(),
|
||||
name: "Phi0".to_string()
|
||||
})
|
||||
// let y_values_phi0 = calc::bit_pattern_randomness_tester(self.a, self.b, self.n_points as u64);
|
||||
// self.plot_data.push(PlotCurve {
|
||||
// points: (0..self.n_points).zip(y_values_phi0.iter()).map(|(x,&y)| [x as f64,y]).collect(),
|
||||
// name: "Phi0".to_string()
|
||||
// })
|
||||
}
|
||||
5 => {
|
||||
let y_values_phi0: Vec<f64> = x_values.iter().map(|&x| {
|
||||
let t0 = Instant::now();
|
||||
let val = calc::phi0(&mut self.calc_cache, x.powi(2), self.n_omnes, self.n_phi0, self.use_tan_omnes, self.use_tan_phi0, self.use_xsub_phi0) / calc::delta_with_lut(&mut self.calc_cache, x.powi(2)) - 1.0;
|
||||
println!("time for x = {}: {:?}", x, t0.elapsed());
|
||||
val
|
||||
}).collect();
|
||||
self.plot_data.push(PlotCurve {
|
||||
points: x_values.iter().zip(y_values_phi0.iter()).map(|(&x,&y)| [x,y]).collect(),
|
||||
name: "Phi0".to_string()
|
||||
})
|
||||
}
|
||||
6_usize.. => {
|
||||
panic!("Not all buttons have been assigned data!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.scaling_type != cur_scaling_type {
|
||||
for curve in self.plot_data.iter_mut() {
|
||||
for [_x,y] in curve.points.iter_mut() {
|
||||
if self.scaling_type == ScalingType::Linear {
|
||||
*y = 10.0f64.powf(*y);
|
||||
} else if self.scaling_type == ScalingType::Logarithmic {
|
||||
*y = y.log10();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let plot = Plot::new("my_plot")
|
||||
.grid_spacing(5.0f32..=300.0f32)
|
||||
.x_axis_label("sqrt(s) [GeV]")
|
||||
.y_axis_label("|Omega|^2")
|
||||
.legend(Legend::default());
|
||||
|
||||
let plot = match self.scaling_type {
|
||||
ScalingType::Linear => plot.custom_y_axes(vec![AxisHints::new_y().formatter(|mark, _l, _| scientific_notation(mark.value, false))]),
|
||||
ScalingType::Logarithmic => {plot.y_grid_spacer(|input| {
|
||||
let input_exp = GridInput {bounds: (inverse_log_map(input.bounds.0), inverse_log_map(input.bounds.1)), base_step_size: input.base_step_size};
|
||||
let lin_gridmarks = (log_grid_spacer(10))(input_exp);
|
||||
let mut log_gridmarks: Vec<GridMark> = Vec::new();
|
||||
for v in lin_gridmarks.iter() {
|
||||
if v.value - v.value.floor() < 0.9 {
|
||||
log_gridmarks.push(GridMark{value:log_map(v.value), step_size:v.step_size / 1.14});
|
||||
}
|
||||
}
|
||||
log_gridmarks
|
||||
})
|
||||
.label_formatter(|_,point| format!("x = {:.5}\ny = {:.5}", point.x, 10.0f64.powf(point.y)).to_string())
|
||||
.custom_y_axes(vec![AxisHints::new_y().formatter(|mark, _l, _| scientific_notation(mark.value, true))])
|
||||
}
|
||||
};
|
||||
|
||||
plot.show(ui, |plot_ui| {
|
||||
for i in 0..self.plot_data.len() {
|
||||
plot_ui.line(Line::new(self.plot_data[i].points.clone()).name(self.plot_data[i].name.clone())); // is clone necessary?
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut app = App::default();
|
||||
app.calc_cache = calc::Cache::from_file("./gauss_quad_lut.morello").unwrap();
|
||||
// let x_values: Vec<f64> = (0..app.n_points).map(|x| -> f64 {f64::from(x) * ((app.b - app.a) / f64::from(app.n_points)) + app.a}).collect();
|
||||
// let t0 = Instant::now();
|
||||
// let y_values_phi0: Vec<f64> = x_values.iter().map(|&x| calc::phi0(&mut app.calc_cache, x, app.n_omnes, app.n_phi0)).collect();
|
||||
// std::hint::black_box(&y_values_phi0);
|
||||
// println!("{:?}", t0.elapsed());
|
||||
|
||||
eframe::run_native("Morellus", eframe::NativeOptions::default(), Box::new(|_cc| Box::new(app))).unwrap();
|
||||
}
|
||||
|
||||
fn log_map(x:f64) -> f64 {
|
||||
x.floor() + (1.0 + (x - x.floor()) * 10.0).log10()
|
||||
}
|
||||
|
||||
fn inverse_log_map(x:f64) -> f64 {
|
||||
x.floor() + (10f64.powf(x - x.floor()) - 1.0) / 10.0
|
||||
}
|
||||
|
||||
fn scientific_notation(x:f64, log:bool) -> String {
|
||||
if log {
|
||||
format!("{}*10^{}", format!(
|
||||
"{:.15}", 10f64.powf(x - x.floor()))
|
||||
.trim_end_matches('0').trim_end_matches('.').to_string(),
|
||||
x.floor()).to_string()
|
||||
} else {
|
||||
format!("{:.9}", x).trim_end_matches('0').trim_end_matches('.').to_string()
|
||||
}
|
||||
}
|
||||
|
||||
fn int_text_edit_singleline(ui: &mut egui::Ui, value: &mut u32) -> egui::Response {
|
||||
let mut tmp_value = format!("{}", value);
|
||||
let res = ui.text_edit_singleline(&mut tmp_value);
|
||||
if let Ok(result) = tmp_value.parse::<u32>() {
|
||||
*value = result;
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn float_text_edit_singleline(ui: &mut egui::Ui, value: &mut f64) -> egui::Response {
|
||||
let mut tmp_value = format!("{}", value);
|
||||
let res = ui.text_edit_singleline(&mut tmp_value);
|
||||
if let Ok(result) = tmp_value.parse::<f64>() {
|
||||
*value = result;
|
||||
}
|
||||
res
|
||||
}
|
19
bachelorarbeit/text.txt
Normal file
19
bachelorarbeit/text.txt
Normal file
@ -0,0 +1,19 @@
|
||||
BTreeMap: 1.2234s
|
||||
phi0_integrand:
|
||||
omnes: 29.30%
|
||||
get: 22.87%
|
||||
integrate_complex: 5.01%
|
||||
delta_with_lut
|
||||
get: 2.50%
|
||||
omnes_integrand: 37.98%
|
||||
delta_with_lut -> get: 22.20%
|
||||
|
||||
HashMap: 1.0767s
|
||||
phi0_integrand:
|
||||
omnes: 35.22%
|
||||
get: 30.40%
|
||||
integrate_complex: 3.95%
|
||||
delta_with_lut
|
||||
get: 1.88%
|
||||
omnes_integrand: 27.21%
|
||||
delta_with_lut -> get: 14.03%
|
34
calc.py
Normal file
34
calc.py
Normal file
@ -0,0 +1,34 @@
|
||||
import math
|
||||
|
||||
m_e = 9.10938e-31
|
||||
e = 1.602e-19
|
||||
pi = 3.141592
|
||||
epsilon_0 = 8.854e-12
|
||||
h_bar = 1.05457e-34
|
||||
h=6.626e-34
|
||||
c=299792458
|
||||
my_B=9.274e-24
|
||||
k_B=1.381e-23
|
||||
avog=6.022e26
|
||||
m_Kalium=39.0983/avog
|
||||
|
||||
def E(n):
|
||||
return -m_e*e**4 / (2*(4*pi*epsilon_0*h_bar*n)**2)
|
||||
|
||||
def dE(n1,n2):
|
||||
return -m_e*e**4 / (2*(4*pi*epsilon_0*h_bar)**2) * (1/n2**2 - 1/n1**2)
|
||||
|
||||
def lamb(E1,E2):
|
||||
return c*h*(E1-E2)**-1
|
||||
|
||||
# print(E(3))
|
||||
# print(E(2))
|
||||
# print(lamb(E(3),E(2)-2*my_B*2)*10**9)
|
||||
Ekin = 3/2*k_B*600
|
||||
v_x = math.sqrt(2*Ekin/m_Kalium)
|
||||
t_acc = 0.2 / v_x
|
||||
F = my_B * 2
|
||||
d = 1/2*F/m_Kalium*t_acc**2
|
||||
v_z_end = F/m_Kalium*t_acc
|
||||
print(v_z_end/v_x)
|
||||
print(1.492+0.1492)
|
280
ersterTest.py
Normal file
280
ersterTest.py
Normal file
@ -0,0 +1,280 @@
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from scipy.special import roots_legendre
|
||||
import cmath
|
||||
from time import time
|
||||
|
||||
# constant values (GeV)
|
||||
|
||||
M_roh = 0.7736
|
||||
M_pi = 0.13957
|
||||
s_0 = 4*M_pi**2
|
||||
M_K = 0.496
|
||||
B_0 = 1.055
|
||||
B_1 = 0.15
|
||||
lambda_1 = 1.57
|
||||
lambda_2 = -1.96
|
||||
lambda_high = 10
|
||||
epsilon = 0.000000001
|
||||
s_mid_high = 1.42**2 # this is the s value, so it is in GeV^2
|
||||
|
||||
# derivative values
|
||||
lambda_0 = 0 # this is fixed by the low energy parametrization: lambda_0 = delta1_low(4M_K**2) (sqrt(s)=2M_K)
|
||||
delta1_mid_high = 0 # again, this is fixed by the value of delta1_mid at 1.42 GeV (see later in the code)
|
||||
|
||||
# Numerical constants
|
||||
gl_n_omnes = 100 # number of points used in the Gauss Legendre Integration
|
||||
gl_n_phi0 = 100
|
||||
|
||||
gl_lookup = {}
|
||||
omnes_lookup = {}
|
||||
delta_lookup = {}
|
||||
|
||||
# Print iterations progress
|
||||
def printProgressBar (iteration, total, prefix = '', suffix = '', decimals = 1, length = 100, fill = '█', printEnd = "\r"):
|
||||
"""
|
||||
Call in a loop to create terminal progress bar
|
||||
@params:
|
||||
iteration - Required : current iteration (Int)
|
||||
total - Required : total iterations (Int)
|
||||
prefix - Optional : prefix string (Str)
|
||||
suffix - Optional : suffix string (Str)
|
||||
decimals - Optional : positive number of decimals in percent complete (Int)
|
||||
length - Optional : character length of bar (Int)
|
||||
fill - Optional : bar fill character (Str)
|
||||
printEnd - Optional : end character (e.g. "\r", "\r\n") (Str)
|
||||
"""
|
||||
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
|
||||
filledLength = int(length * iteration // total)
|
||||
bar = fill * filledLength + '-' * (length - filledLength)
|
||||
print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)
|
||||
# Print New Line on Complete
|
||||
if iteration == total:
|
||||
print()
|
||||
|
||||
''' the standard implementation of arctan gives angles in (-pi/2, pi/2). This gives angles in (0, pi). Note: This doesn't imply a simple shift of all values by pi, but a transposition of the results from (-pi/2, 0) to (pi/2, pi).'''
|
||||
def arctan_shift(x):
|
||||
atan_std = np.arctan(x)
|
||||
if atan_std < 0:
|
||||
return atan_std + np.pi
|
||||
return atan_std
|
||||
|
||||
def log_shift(x):
|
||||
log_std = cmath.log(x)
|
||||
if log_std.imag < 0:
|
||||
return 2*np.pi*1j + log_std
|
||||
else:
|
||||
return log_std
|
||||
|
||||
def omega(s):
|
||||
# in this instance, Elena uses s_0**(1/2) = 1.05 GeV, but later she uses s_0 = 4*M_pi**2
|
||||
a = np.sqrt(s)
|
||||
b = np.sqrt(1.05**2 - s)
|
||||
return (a - b) / (a + b)
|
||||
|
||||
|
||||
# ----------------
|
||||
# Delta function section
|
||||
# ----------------
|
||||
|
||||
def k(s):
|
||||
return np.sqrt(s/4-M_pi**2)
|
||||
|
||||
def delta1_low(s):
|
||||
#a = np.sqrt(s) / (2*k(s)**3) * (M_roh**2 - s) * ( (2*M_pi**3) / (M_roh**2*np.sqrt(s)) + B_0 + B_1*omega(s) )
|
||||
return arctan_shift((np.sqrt(s) / (2*k(s)**3) * (M_roh**2 - s) * ( (2*M_pi**3)/(M_roh**2*np.sqrt(s)) + B_0 + B_1*omega(s)))**-1)
|
||||
|
||||
def delta1_mid(s):
|
||||
return lambda_0 + lambda_1 * (0.5*np.sqrt(s) / M_K - 1) + lambda_2 * (0.5*np.sqrt(s) / M_K - 1)**2
|
||||
|
||||
def delta1_high(s):
|
||||
return np.pi + (delta1_mid_high - np.pi) * (lambda_high**2 + s_mid_high) / (lambda_high**2 + s)
|
||||
|
||||
|
||||
def delta(s):
|
||||
# if s in delta_lookup:
|
||||
# return delta_lookup[s]
|
||||
# if s < (2*M_K)**2:
|
||||
# delta_lookup[s] = delta1_low(s)
|
||||
# elif s < s_mid_high:
|
||||
# delta_lookup[s] = delta1_mid(s)
|
||||
# else:
|
||||
# delta_lookup[s] = delta1_high(s)
|
||||
# return delta_lookup[s]
|
||||
if s < (2*M_K)**2:
|
||||
return delta1_low(s)
|
||||
elif s < s_mid_high:
|
||||
return delta1_mid(s)
|
||||
else:
|
||||
return delta1_high(s)
|
||||
|
||||
|
||||
# set cutoff values
|
||||
lambda_0 = delta1_low((2*M_K)**2)
|
||||
delta1_mid_high = delta1_mid(s_mid_high)
|
||||
|
||||
|
||||
# ----------------
|
||||
# Omnes Integral section
|
||||
# ----------------
|
||||
|
||||
delta_time = 0
|
||||
|
||||
def omnes_integrand(s_tick,s):
|
||||
global delta_time
|
||||
delta_s_tick = delta(s_tick)
|
||||
delta_s = delta(s)
|
||||
return (delta_s_tick - delta_s)/(s_tick*(s_tick-s+epsilon*1j))
|
||||
|
||||
|
||||
def integral_gl(f,s,a,b,n, prog=False):
|
||||
if n not in gl_lookup:
|
||||
# print("now calculating roots, weights")
|
||||
t0 = time()
|
||||
gl_lookup[n] = roots_legendre(n)
|
||||
#print("time to calculate roots and weights with n={}: {} seconds".format(n,time() - t0))
|
||||
roots, weights = gl_lookup[n]
|
||||
sum = 0
|
||||
for i in range(n):
|
||||
if prog:
|
||||
printProgressBar(i,n)
|
||||
sum += weights[i]*f(roots[i]*(b-a)/2 + (a+b)/2,s)
|
||||
sum *= (b-a)/2
|
||||
return sum
|
||||
|
||||
def subst(f, phi, phi_deriv):
|
||||
return lambda x,s : f(phi(x),s)*phi_deriv(x)
|
||||
|
||||
def integral_gl_tan_reparam(f,s,a,b,n, prog=False):
|
||||
return integral_gl(subst(f,np.tan,lambda x : (1 / np.cos(x)**2)),s,np.arctan(a),np.pi / 2,n,prog)
|
||||
|
||||
def omnes(s, a=s_0, inf = 10000000000, optimized = True, n = gl_n_omnes):
|
||||
if s in omnes_lookup:
|
||||
return omnes_lookup[s]
|
||||
elif optimized:
|
||||
analyt = delta(s) / s * cmath.log(((inf-s-epsilon*1j)*a) / ((a-s-epsilon*1j)*inf))
|
||||
res = cmath.exp(s/np.pi*(integral_gl_tan_reparam(omnes_integrand,s,a,inf,n) + analyt))
|
||||
#omnes_lookup[s] = res
|
||||
return res
|
||||
else:
|
||||
res = cmath.exp(s/np.pi*(integral_gl(omnes_integrand,s,a,inf,n)+delta(s) / s * cmath.log(((inf-s-epsilon*1j)*a) / ((a-s-epsilon*1j)*inf))))
|
||||
#omnes_lookup[s] = res
|
||||
return res
|
||||
# A more easily readible version of the formula
|
||||
# if optimized == True:
|
||||
# m = integral_gl_tan_reparam(omnes_integrand,s,a,inf,n)-
|
||||
# else:
|
||||
# m = integral_gl(omnes_integrand,s,a,inf,n)
|
||||
# n = ((inf-s-epsilon*1j)*a) / ((a-s-epsilon*1j)*inf)
|
||||
# p = delta(s) / s * cmath.log(n)
|
||||
# omnes_lookup[s] = cmath.exp(s/np.pi*(m+p))
|
||||
# if s > 0.74**2 and s < 0.76**2:
|
||||
# print(s, m, n, p, cmath.exp(s/np.pi*(m+p)))
|
||||
# return cmath.exp(s/np.pi*(m+p))
|
||||
|
||||
# ----------------
|
||||
# Phase reconstruction section
|
||||
# ----------------
|
||||
|
||||
def phi0_integrand_bad(s_tick, s):
|
||||
omnes_s = omnes(s)
|
||||
omnes_s_tick = omnes(s_tick)
|
||||
#a = np.log(cmath.polar(omnes_s_tick / omnes_s)[0]**2)
|
||||
#b = np.sqrt(s_tick - s_0) * s_tick * (s_tick - s)
|
||||
return np.log(cmath.polar(omnes_s_tick / omnes_s)[0]**2) / (np.sqrt(s_tick - s_0) * s_tick * (s_tick - s))
|
||||
|
||||
def phi0_integrand(x, s):
|
||||
omnes_s = omnes(s)
|
||||
omnes_x = omnes(x**2 + s_0)
|
||||
|
||||
#a = np.log(cmath.polar(omnes_s_tick / omnes_s)[0]**2)
|
||||
#b = np.sqrt(s_tick - s_0) * s_tick * (s_tick - s)
|
||||
return 2*np.log(cmath.polar(omnes_x / omnes_s)[0]**2) / ((s_0 + x**2) * (s_0 + x**2 - s))
|
||||
|
||||
def phi0(s, a=0, inf = 100000, optimized = True, n = gl_n_phi0):
|
||||
c = np.pi / (s * np.sqrt(s_0)) * np.log(cmath.polar(omnes(s))[0]**2)
|
||||
|
||||
if optimized == True:
|
||||
integral = integral_gl_tan_reparam(phi0_integrand, s, a, inf, n, False)
|
||||
else:
|
||||
integral = integral_gl(phi0_integrand, s, a, inf, n)
|
||||
return -s * np.sqrt(s-s_0) / (2*np.pi) * (integral - c)
|
||||
|
||||
# ----------------
|
||||
# Plotting section
|
||||
# ----------------
|
||||
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
|
||||
# these are sqrt(s) values, not s
|
||||
x = np.linspace(s_0**0.5+0.001,3,500)
|
||||
#x = np.linspace(0.7, 0.85, 500)
|
||||
x_to_pi2 = np.linspace(np.arctan(s_0)**0.5+0.001,(np.pi/2)**0.5,5000)
|
||||
|
||||
y_delta = [delta(i**2) for i in x]
|
||||
#y1 = [cmath.polar(omnes_integrand(i**2,0.73))[0]**2 for i in x]
|
||||
#y2 = [cmath.polar(omnes_integrand(i**2,0.73965))[0]**2 for i in x]
|
||||
#y3 = [cmath.polar(omnes_integrand(i**2,0.75))[0]**2 for i in x]
|
||||
#y_omnes_integrand_tan = [cmath.polar(omnes_integrand(np.tan(i**2),2) / np.cos(i**2)**2)[0]**2 for i in x_to_pi)]
|
||||
#y_omnes_acc = [cmath.polar(omnes(i**2, optimized=True))[0]**2 for i in x]
|
||||
#y_omnes_best = [cmath.polar(omnes(i**2, inf=10000, n = 10000))[0]**2 for i in x]
|
||||
#y_phi0_integrand = [phi0_integrand(i**2, 2) for i in x]
|
||||
#y_phi0_integrand_tan = [phi0_integrand(np.tan(i**2), 0.8)*1/np.cos(i**2)**2 for i in x_to_pi2]
|
||||
#y_phi0_integrand_tan2 = [phi0_integrand(np.tan(i**2), 10000)*1/np.cos(i**2)**2 for i in x_to_pi2]
|
||||
#y_phi0_integrand2 = [phi0_integrand(i**2, 0.8035457451490298) for i in x_phi0]
|
||||
|
||||
'''
|
||||
for n in [10,100,1000,10000]:
|
||||
print("Phi0 for n_omnes={}, n_phi0={}: {}".format(gl_n_omnes, n, phi0(100**2, n=n)))
|
||||
'''
|
||||
|
||||
'''
|
||||
n_values = [10,100,1000,10000,100000]
|
||||
y_phi0 = [[] for _ in n_values]
|
||||
for (i_n,n) in enumerate(n_values):
|
||||
|
||||
# for (i,val) in enumerate(x):
|
||||
# y_phi0[i_n].append(phi0(val**2, n = n))
|
||||
# printProgressBar(i,len(x))
|
||||
print("Ready with {}".format(n))
|
||||
print()
|
||||
'''
|
||||
# Test sensitivity of phi0 to n compared to omnes
|
||||
'''
|
||||
n_values = np.arange(5, 4000, 25)
|
||||
y_omnes_n_cmp = [cmath.polar(omnes(0.8**2, n=i))[0]**2 for i in n_values]
|
||||
y_phi0_n_cmp = [phi0(0.8**2, n=i) for i in n_values]
|
||||
ax.plot(n_values, y_omnes_n_cmp, label = "omnes")
|
||||
ax.plot(n_values, y_phi0_n_cmp, label = "phi0")
|
||||
'''
|
||||
|
||||
ax.plot(x, y_delta, label = r"$\delta$")
|
||||
#ax.plot(x, y2, label = "delta")
|
||||
#ax.plot(x, y3, label = "delta")
|
||||
#ax.plot(x_to_pi2, y_omnes_integrand_tan, label = r"$\Omega$ integrand w/ tan-param.")
|
||||
#ax.plot(x, y_omnes, label = r'${|\Omega (s)|}^2$')
|
||||
#ax.plot(x, y_omnes_acc, label = r'${|\Omega (s)|}^2$, reparam')
|
||||
#ax.plot(x, y_omnes_best, label = r'${|\Omega (s)|}^2$, but best')
|
||||
#ax.plot(x, y_phi0_integrand, label = r'$\phi_0$ Integrand')
|
||||
#ax.plot(x_to_pi2, y_phi0_integrand_tan, label = r'$\phi_0$ integrand w/ tan-param.')
|
||||
#ax.plot(x_to_pi2, y_phi0_integrand_tan2, label = r'$\phi_0$ integrand w/ tan-param, s=10000.')
|
||||
#ax.plot(x_phi0, y_phi0_integrand2, label = r'$\phi_0$ Integrand2')
|
||||
#for (i,y) in enumerate(y_phi0):
|
||||
#ax.plot(x, y, label = r'$\phi_0, n={}$'.format(i))
|
||||
|
||||
# t0 = time()
|
||||
# y_phi0 = [phi0(i**2) for i in x]
|
||||
# ax.plot(x, y_phi0)
|
||||
# print(time() - t0)
|
||||
|
||||
t0 = time()
|
||||
print(phi0(10000, n=100))
|
||||
print(time() - t0)
|
||||
|
||||
# ax.legend()
|
||||
# #plt.yscale('log')
|
||||
# ax.grid(which='major', color='#A4A4A4', linewidth=1)
|
||||
# ax.grid(which='minor', color='#B5B5B5', linestyle=':', linewidth=0.5)
|
||||
# ax.minorticks_on()
|
||||
# plt.show()
|
Loading…
x
Reference in New Issue
Block a user