├── .gitattributes ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .vscode └── settings.json ├── InstallPkg.jl ├── MANIFEST.in ├── README.md ├── build └── lib │ └── pyLLE │ ├── ComputeLLE.jl │ ├── __init__.py │ ├── _analyzedisp.py │ └── _llesolver.py ├── example ├── DKS_init.csv ├── RW1000_H430.csv └── TemporalDualPump.ipynb ├── images └── NISTlogo32x32.jpg ├── licence.txt ├── pyLLE ├── ComputeLLE.jl ├── __init__.py ├── _analyzedisp.py └── _llesolver.py ├── pypiStuff ├── build │ └── lib │ │ └── pyLLE │ │ ├── ComputeLLE.jl │ │ ├── __init__.py │ │ ├── _analyzedisp.py │ │ └── _llesolver.py └── dist │ ├── pyLLE-4.0.1-py3-none-any.whl │ ├── pyLLE-4.0.1-py3.9.egg │ └── pyLLE-4.0.1.tar.gz ├── requirements.txt └── setup.py /.gitattributes: -------------------------------------------------------------------------------- 1 | docs/* linguist-vendored 2 | images/* linguist-vendored 3 | example/* linguist-vendored -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior. Please post a minimal working example 12 | 13 | **Expected behavior** 14 | A clear and concise description of what you expected to happen. 15 | 16 | **Error or Screenshots** 17 | Copy here the entire error that you obtain. And/or If applicable, add screenshots to help explain your problem. 18 | 19 | **Desktop (please complete the following information):** 20 | - OS: [e.g. Debian, Mac OS 10.14] 21 | - Python version 22 | - Julia version 23 | 24 | **Additional context** 25 | Add any other context about the problem here. 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # exclude everything except directory foo/bar 2 | pyLLE.egg-info* 3 | .gitignore 4 | Icon* 5 | Icon^M 6 | .DS_Store 7 | Stable 8 | pipDeploy 9 | *.pyc 10 | .ipynb_checkpoints 11 | dist 12 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.formatting.provider": "black" 3 | } -------------------------------------------------------------------------------- /InstallPkg.jl: -------------------------------------------------------------------------------- 1 | using Pkg 2 | 3 | Pkg.add("HDF5") 4 | Pkg.update("HDF5") 5 | 6 | Pkg.add("FFTW") 7 | Pkg.update("FFTW") 8 | 9 | Pkg.add("LinearAlgebra") 10 | Pkg.update("LinearAlgebra") 11 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include InstallPkg.jl 2 | include pyLLE/ComputeLLE.jl -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pyLLE ![NIST logo](images/NISTlogo32x32.jpg) 2 | 3 | [![](https://img.shields.io/static/v1.svg?label=docs&message=passing&color=green&style=flat)](https://gregmoille.github.io/pyLLE/) 4 | ![](https://img.shields.io/static/v1.svg?label=version&message=4.1&color=9cf&style=flat) 5 | [![](https://img.shields.io/static/v1.svg?label=DOI&message=10.6028/jres.124.012&color=blue&style=flat)](https://doi.org/10.6028/jres.124.012) 6 | 7 | ## What's new 8 | 9 | A major revision, v4.0.0 introduces a lot of new stuff including: 10 | 11 | - Complete recoding of the core with better coding and commenting which hopefully makes it easier to implement custom features 12 | - Modification of interfacing with parameters and results through method attributes instead of bulky dictionaries 13 | - Stability of the half step Fourier method, allowing to use a soliton solution as an original state for the LLE 14 | - Allowing arbitrary number of driving pump, according to Taheri et al The European Physical Journal D 2017. and our paper on Nature Communication (Moille et al. Nature Communication 2021) 15 | - **Julia compatibility with version 1.8 (current as of 05/01/2023) and above**. Previous version are no longer supported 16 | 17 | ## How to Cite Us? 18 | 19 | Please, if you use this package and it helps you with your research and publication, cite us in your paper. Not only does it allow us to have a better idea of new things people are interested in and how to keep improving the solver, but it also helps us build a community where everybody can help maintain the solver to better suit the needs of everybody. 20 | You can cite our paper published in the Journal of Research of the National Institute of Standards and Technology, available [here](https://doi.org/10.6028/jres.124.012), with the following BibTeX entry.: 21 | 22 | ```latex 23 | @article{moille_pyLLE, 24 | author = {Gregory Moille and Qing Li and Xiyuan Lu and Kartik Srinivasan}, 25 | title = {pyLLE: a Fast and User Friendly Lugiato-Lefever Equation Solver}, 26 | year = {2019}, 27 | volume = {124}, 28 | pages = {124012}, 29 | month = {2019-05-24}, 30 | journal = {Journal of Research of the NIST}, 31 | doi = {https://doi.org/10.6028/jres.124.012}, 32 | } 33 | ``` 34 | 35 | ## How to install 36 | 37 | As pyLLE relies on a Julia back-end, please prior to installing this package be sure that Julia is installed on your machine or visit the julia [package download page](https://julialang.org/downloads/) to install it. The code should now work with any recent version of Julia. 38 | 39 | Once Julia installed, the different packages needed to run pyLLE, either python or julia related, will be automatically downloaded and installed. Just a heads up, the installation of the package can vary in time, especially because of Julia that might rebuild the cache. 40 | 41 | pyLLE will look by default to find the Julia binary in the `/opt/bin/julia`, which you can make it happen either in MacOS 42 | 43 | ```bash 44 | ln -s /Applications/Julia-.app/Contents/Resources/julia/bin/julia /opt/bin/julia 45 | ``` 46 | 47 | or Linux 48 | 49 | ```bash 50 | ln -s /bin/julia /opt/bin/julia 51 | ``` 52 | 53 | Note that if this step is skipped it is alright as an update of the pyLLE package provide a way to specify the julia binary you would like to use specifyin `solver.SolveTemporal(bin = )` 54 | 55 | Now, one can simply automatic install, just pip it : 56 | 57 | ```bash 58 | pip install pyLLE 59 | ``` 60 | 61 | or pip the github 62 | 63 | ```bash 64 | pip install git+https://github.com/gregmoille/pyLLE.git 65 | ``` 66 | 67 | 68 | **For windows** the julia package have to be installed manually, using a julia console and typing the following command: 69 | 70 | ```julia 71 | using Pkg 72 | 73 | Pkg.add("HDF5") 74 | Pkg.update("HDF5") 75 | 76 | Pkg.add("FFTW") 77 | Pkg.update("FFTW") 78 | 79 | Pkg.add("LinearAlgebra") 80 | Pkg.update("LinearAlgebra") 81 | 82 | ``` 83 | 84 | 85 | For a manual install, download the .zip of the repository or clone it and install with the setup.py script. 86 | 87 | ## Checking that everything works correctly 88 | 89 | Launch a julia console and within type the commands: 90 | 91 | ```julia 92 | using HDF5 93 | using FFTW 94 | using LinearAlgebra 95 | ``` 96 | 97 | if any of the previous command throw an issue, mostly it is because it is not installed. One way to fix it is to remove the installed packaged to remove the cache 98 | 99 | - for linux and mac os user: remove everything in ~/.julia/ 100 | - for windows users: remove everything in C:\Users\\.julia\ 101 | 102 | Then enter the pacakge manager for julia by typing in the julia console: 103 | 104 | ```julia 105 | julia>] 106 | ``` 107 | 108 | then 109 | 110 | ```julia 111 | (v1.1) pkg>add HDF5 112 | (v1.1) pkg>add FFTW 113 | ``` 114 | 115 | ## Example [![NBviewer](https://custom-icon-badges.demolab.com/badge/jupyter-notebook-blue.svg?logo=eye&logoColor=white)](https://nbviewer.org/github/gregmoille/pyLLE/blob/master/example/TemporalDualPump.ipynb) 116 | 117 | A complete example is available in the example directory [notebook](https://github.com/gregmoille/pyLLE/blob/master/example/TemporalDualPump.ipynb) with the corresponding file needed in the folder. 118 | You can also access the [nbviewer](https://nbviewer.org/github/gregmoille/pyLLE/blob/master/example/TemporalDualPump.ipynb) example to have a better idea of what's going on: 119 | 120 | ## Works Using/citing pyLLE 121 | 122 | If you want to be featured here, shoot me an email! I try to keep it up to date but this is not a priority. I would love to hear anybody who uses it! 123 | - 2025: 124 | - Moille, G. et al. Versatile optical frequency division with Kerr-induced synchronization at tunable microcomb synthetic dispersive waves. Nat. Photon. 19, 36–43 (2025). 125 | - Shandilya, P. et al. All-optical azimuthal trapping of dissipative Kerr multi-solitons for relative noise suppression. APL Photonics 10, 016104 (2025). 126 | - 2024: 127 | - Moille, G., Shandilya, P., Erkintalo, M., Menyuk, C. R. & Srinivasan, K. On-Chip Parametric Synchronization of a Dissipative Kerr Soliton Microcomb. Preprint at https://doi.org/10.48550/arXiv.2409.05388 (2024). 128 | - Moille, G., Westly, D. & Srinivasan, K. Broadband Visible Wavelength Microcomb Generation In Silicon Nitride Microrings Through Air-Clad Dispersion Engineering. Preprint at https://doi.org/10.48550/arXiv.2404.01577 (2024). 129 | - 2023: 130 | - Moille, G., Stone, J., Chojnacky, et al. Kerr-Induced Synchronization of a Cavity Soliton to an Optical Reference. Nature 624, 267–274 (2023). 131 | - Moille, G., Lu, X., Stone, J., Westly, D., & Srinivasan, K. (2023). Fourier synthesis dispersion engineering of photonic crystal microrings for broadband frequency combs. Communications Physics, 6(1), 144. 132 | - Ren, D., Dong, C., & Burghoff, D. Integrated nonlinear photonics in the longwave-infrared: A roadmap. MRS Communications, 13(6), 942-956 (2023). 133 | - Ji, H., Geng, Z., Cheng, W., Wu, P., Yu, Z., Liu, Y., ... & Zhao, Q. (2023). High-power two-color Kerr frequency comb generation on the gallium phosphide-on-insulator platform at SWIR and MIR spectra. JOSA B, 40(8), 1976-1985. 134 | - Geng, Z., Ji, H., Yu, Z., Cheng, W., Wu, P., Li, Y., & Zhao, Q. (2023). Dispersion-flattened concentric structure for microcomb bandwidth broadening in GaP-OI resonators. JOSA B, 40(3), 673-681. 135 | - Moille, G., Li, C., Stone, J., Chojnacky, M., Shandilya, P., Chembo, Y. K., Dutt, A., ... & Srinivasan, K. (2023). Two-Dimensional Nonlinear Mixing Between a Dissipative Kerr Soliton and Continuous Waves for a Higher-Dimension Frequency Comb. arXiv preprint arXiv:2303.10026. 136 | - 2022: 137 | - Afridi, A. A., Weng, H., Li, J., Liu, J., McDermott, M., Lu, Q., ... & Donegan, J. F. (2022). Breather solitons in AlN microresonators. Optics Continuum, 1(1), 42-50. 138 | - Lu, S., Liu, X., Shi, Y., Yang, H., Long, Z., Li, Y., ... & Liang, H. (2022). Mid-infrared ultra-broadband optical Kerr frequency comb based on a CdTe ring microresonator: a theoretical investigation. Optics express, 30(19), 33969-33979. 139 | - 2021: 140 | - Weng, H., Liu, J., Afridi, A. A., Li, J., Dai, J., Ma, X. _et al._ "_Octave-spanning Kerr frequency comb generation with stimulated Raman scattering in an AlN microresonator_". Optics Letters, 46(3), 540-543. (2021) 141 | - Weng, H., Liu, J., Afridi, A. A., Li, J., Dai, J., Ma, X. _et al._ "_Directly accessing octave-spanning dissipative Kerr soliton frequency combs in an AlN microring resonator_" Photonics Research (2021) 142 | - Moille, G., Westly, D., Orji, N. G., & Srinivasan, K. "_Tailoring broadband Kerr soliton microcombs via post-fabrication tuning of the geometric dispersion_". Applied Physics Letters, 119(12), 121103 (2021) 143 | - Weng, H., Liu, J., Afridi, A. A., Li, J., Dai, J., Zhang, Y., _et al._ "_Perfect soliton crystal in an AlN microresonator"_. In CLEO: QELS_Fundamental Science (pp. JTh3A-31). Optical Society of America. (2021) 144 | - Moille, G., Westly, D., Simelgor, G., & Srinivasan, K. "_Impact of the precursor gas ratio on dispersion engineering of broadband silicon nitride microresonator frequency combs_". Optics 145 | Letters, 46(23), 5970-5973 (2021). 146 | - 2020: 147 | - Schuttrups, B. (2020). "_Modelling nonlinear optical pulse propagation using pseudo-spectral methods_" (Master's thesis, University of Twente). 148 | - Moille, G., Chang, L., Xie, W., Rao, A., Lu, X., Davanco, M. _et al._ "_Dissipative Kerr Solitons in a III‐V Microresonator_". Laser & Photonics Reviews, 14(8), 2000022 (2020) 149 | -2019: 150 | - Gregory Moille, Xiyuan Lu, Ashutosh Rao, Qing Li, Daron A. Westly, Leonardo Ranzani, Scott B. Papp, Mohammad Soltani, and Kartik Srinivasan "_Kerr-Microresonator Soliton Frequency Combs at Cryogenic Temperatures_," Phys. Rev. Applied 12, 034057 (2019) 151 | - Gregory Moille, Qing Li, Travis C. Briles, Su-Peng Yu, Tara Drake, Xiyuan Lu, Ashutosh Rao, Daron Westly, Scott B. Papp, and Kartik Srinivasan "_Broadband resonator-waveguide coupling for efficient extraction of octave-spanning microcombs_," Optics Letters Vol. 44, Issue 19, pp. 4737-4740 (2019) 152 | - Lin Chang, Weiqiang Xie, Haowen Shu, Qifan Yang, Boqiang Shen, Andreas Boes, Jon D. Peters, Warren Jin, Songtao Liu, Gregory Moille, Su-Peng Yu, Xingjun Wang, Kartik Srinivasan, Scott B. Papp, Kerry Vahala, John E. Bowers "_Ultra-efficient frequency comb generation in AlGaAs-on-insulator microresonators_," arXiv:1909.09778 (2019) 153 | -------------------------------------------------------------------------------- /build/lib/pyLLE/ComputeLLE.jl: -------------------------------------------------------------------------------- 1 | using HDF5 2 | using Base 3 | using FFTW 4 | using LinearAlgebra 5 | 6 | function Loadh5Param(dir) 7 | h5file = dir * "ParamLLEJulia.h5" 8 | res = Dict() 9 | sim = Dict() 10 | sim_name = ["res", "sim"] 11 | par = [["Qc", "R", "ng", "Qi", "gamma","dispfile"], ["Pin", "Tscan", "domega_init", "domega_end", "domega_stop", "domega", "f_pmp", "mu_sim_center", "ind_pmp", "Dint", "ind_pump_sweep","f_center", "phi_pmp", "D1", "DKSinit_imag","DKSinit_real", "num_probe"]] 12 | cnt = 1 13 | for sim_par = [res, sim] 14 | for it = par[cnt] 15 | sim_par[it] = h5read(h5file, sim_name[cnt] *"/" * it) 16 | end 17 | cnt += 1 18 | end 19 | 20 | return res, sim 21 | end 22 | 23 | 24 | function SaveResultsToFile(dir, S) 25 | h5file = dir * "ResultsJulia.h5" 26 | println(h5file) 27 | println("\n") 28 | sleep(1) 29 | 30 | h5open(h5file, "w") do file 31 | g = create_group(file, "Results") # create a group 32 | for ii in S 33 | print(ii[1]) 34 | print("\n") 35 | g[ii[1]*"Real"] = real(ii[2]) # create a scalar dataset inside the group 36 | g[ii[1]*"Imag"] = imag(ii[2]) 37 | end 38 | # attrs(g)["Description"] = "This group contains only a single dataset" 39 | end 40 | end 41 | 42 | # ---------------------------------------------------- 43 | # -- STARTING MAIN SCRIPT -- 44 | # ---------------------------------------------------- 45 | tmp_dir = ARGS[1] #"/var/folders/_v/2zfybdtj589c1fwk78q_q5qr0000gn/T/tmpqmatmei5" # 46 | tol = parse(Float64,ARGS[2]) #1e-3 # 47 | maxiter = parse(Int,ARGS[3]) #10 # 48 | stepFactor = parse(Float64,ARGS[4]) #1# 49 | 50 | # tmp_dir = "/tmp/tmpbyi6lbwx" 51 | res, sim = Loadh5Param(tmp_dir) 52 | logfile = open(tmp_dir * "Log.log" ,"w") 53 | 54 | # ---------------------------------------------------- 55 | # -- Collect Data --- 56 | # ---------------------------------------------------- 57 | c0 = 299792458 58 | ħ = 6.634e-34/2/pi 59 | 60 | # -- res parameters -- 61 | ng = res["ng"][1] 62 | R = res["R"][1] 63 | γ = res["gamma"][1] 64 | L = 2*pi*R 65 | 66 | Q0 = res["Qi"][1] 67 | Qc = res["Qc"][1] 68 | fpmp = sim["f_pmp"] 69 | Ppmp = sim["Pin"] 70 | φpmp = sim["phi_pmp"] 71 | num_probe = sim["num_probe"][1] 72 | fcenter= sim["f_center"][1] 73 | 74 | DKSinit_real = sim["DKSinit_real"] 75 | DKSinit_imag = sim["DKSinit_imag"] 76 | 77 | DKSinit = DKSinit_real .+ 1im .* DKSinit_imag 78 | 79 | D1= sim["D1"][1] 80 | FSR = D1/2π 81 | ω0 = 2π*fpmp 82 | ωcenter = 2π*fcenter 83 | 84 | # -- Setup the different Parameters -- 85 | # ---------------------------------------------------- 86 | tR = 1/FSR 87 | T = 1*tR 88 | κext = ω0[1]/Qc*tR 89 | κ0 = ω0[1]/Q0*tR 90 | α = κ0 + κext 91 | # -- Retrieve sim parameters -- 92 | # ---------------------------------------------------- 93 | # debug = Bool(sim["debug"][1]) 94 | δω_init = sim["domega_init"][1] 95 | δω_end = sim["domega_end"][1] 96 | δω_stop = sim["domega_stop"][1] 97 | ind_sweep = sim["ind_pump_sweep"] .+ 1 #because of 0 and 1 index start difference between Julia nd pyhton 98 | t_end = sim["Tscan"][1] 99 | Dint = sim["Dint"] 100 | 101 | 102 | δω = sim["domega"] 103 | ind_pmp = [ii+1 for ii in sim["ind_pmp"]] #because of 0 and 1 index start difference between Julia 104 | μ_sim = sim["mu_sim_center"] 105 | μ = collect(μ_sim[1]:μ_sim[2]) 106 | μ0 = Int(1 + (length(μ)-1)/2) # center of the domain 107 | 108 | # -- Losses -- 109 | # ---------------------------------------------------- 110 | dω = collect(μ_sim[1]:μ_sim[end])*2*pi*FSR 111 | dω_pmp1 = collect(μ_sim[1]-ind_pmp[1]-1:μ_sim[end]-ind_pmp[1]-1)*2*pi*FSR 112 | ω1 = ω0[1] .+ dω_pmp1 113 | 114 | # Make sure there is no residue in the center of the domain 115 | Dint= (Dint .- Dint[μ0]) 116 | # dφ_Kerr=κext*Pin*γ*L/α^2 117 | 118 | Ptot = 0 119 | for ii=1:length(fpmp) 120 | global Ptot += Ppmp[ii] 121 | end 122 | # dt=0.2/(sqrt(Ptot)) 123 | dt = 1 124 | t_end = t_end*tR 125 | t_ramp = t_end 126 | 127 | # -- Sim length -- 128 | # ---------------------------------------------------- 129 | Nt = round(t_ramp/tR/dt) 130 | t1 = 0 131 | 132 | # -- Angle through the resonator -- 133 | # ---------------------------------------------------- 134 | θ = Array(range(0,stop=2π,length=length(μ))) 135 | # -- Time scale --- 136 | # Here the normaizatiton of time is such that 137 | # t=0 when the pump is align with the cold cavity 138 | # δω=0 → t=0- 139 | # hence we need to rescale if the detuning is not symmetric 140 | # ---------------------------------------------------- 141 | δωtot = (abs(δω_end) + abs(δω_init)) 142 | δωcent_perc = -1*sign(δω_end+δω_init)*(abs(δω_end + δω_init)/2)/δωtot 143 | t_sim = Array(range(-t_ramp/2 + δωcent_perc*t_ramp, 144 | stop = t_ramp/2 + δωcent_perc*t_ramp, 145 | length=Int(Nt))) 146 | 147 | # -- Frequency sweep --- 148 | # index = 1 will always be the main pump, i.e. from where the Dint is defined 149 | # δω_init = δω_init * tR 150 | # δω_end = δω_end * tR 151 | # ---------------------------------------------------- 152 | xx = collect(1:Nt) 153 | 154 | δω_all = [δω[ii]*ones(Int(Nt),1) for ii in collect(1:length(fpmp))] 155 | # define which thing we are actually sweeping 156 | for ii in ind_sweep 157 | δω_all[ii][:] = δω_init.+ xx/Nt * (δω_end - δω_init) 158 | # δω_all[2][δω_all[ii] .< δω_stop] .= 1 .* δω_all[2][δω_all[ii] .< δω_stop] 159 | # δω_all[ii][δω_all[ii] .< δω_stop] .= δω_stop 160 | end 161 | 162 | 163 | 164 | # -- Seting up Simulation -- 165 | # ---------------------------------------------------- 166 | # -- Allocate FFT to go faster -- 167 | ifft_plan = FFTW.plan_ifft(zeros(length(μ), 1)) 168 | fft_plan = FFTW.plan_fft(zeros(length(μ), 1)) 169 | 170 | # -- Define the noise 171 | # ---------------------------------------------------- 172 | function Noise() 173 | Ephoton=ħ.*ω1 174 | phase=2*pi*(rand(length(μ),1)) 175 | array=rand(length(μ),1) 176 | Enoise=array.*sqrt.(Ephoton/2).*exp.(1im*phase).*length(μ) 177 | return FFTW.ifftshift(ifft_plan*(Enoise)) # not that ifftshift matters much here but let's do it right 178 | end 179 | 180 | # -- Pumps input -- 181 | # Need to detune them from the center of the domain (first index) 182 | # Need to do it rhough FFT as it seems in the temporal domain 183 | # introducing a shift through exp(μj x θ) introduce bunch of noise 184 | # --------------------------------------------------------------- 185 | Ain = [1im*zeros(length(μ),1) for ii in collect(1:length(fpmp))] 186 | Ein = [1im*zeros(length(μ),1) for ii in collect(1:length(fpmp))] 187 | for ii in collect(1:length(fpmp)) 188 | Ein[ii][μ0+ind_pmp[ii]] = sqrt(Ppmp[ii])*length(μ) 189 | Ain[ii] = ifft_plan*(FFTW.fftshift(Ein[ii])) .* exp(-1im.*φpmp[ii]) 190 | end 191 | # -- Initial State -- 192 | # --------------------------------------------------------------- 193 | u0 = 1im * zeros(length(μ),1) 194 | u0[:, 1] = DKSinit 195 | 196 | # -- Output Dict -- 197 | # --------------------------------------------------------------- 198 | S = Dict() 199 | # num_probe= 5000 200 | S["u_probe"] = 1im*zeros(num_probe, length(u0)) 201 | S["driving_force"] = 1im*zeros(num_probe,length(u0)) 202 | S["detuning"] = zeros(num_probe,) 203 | S["t_sim"] = zeros(num_probe,) 204 | S["kappa_ext"] = [κext] 205 | S["kappa_0"] = [κ0] 206 | S["alpha"] = [α] 207 | 208 | # -- Misc -- 209 | # --------------------------------------------------------------- 210 | 211 | Dint_shift = FFTW.ifftshift(Dint) 212 | # --------------------------------------------------------------- 213 | # ------------------------------------------ 214 | # -- Define the Functions 215 | # ------------------------------------------ 216 | # --------------------------------------------------------------- 217 | 218 | function ProgressBar_CallBack(it, Nt, S, u0, param) 219 | # -- Update the Progress Bar function every % -- 220 | if it/Nt >= param["probe_pbar"] 221 | param["cnt_pbar"] = param["cnt_pbar"] + 1; 222 | #print(string(Int(round(param["probe_pbar"]*100))) * "\n"); 223 | logfile = open(tmp_dir * "log.log" ,"a") 224 | write(logfile,string(Int(round(param["probe_pbar"]*100))) * "\n") 225 | close(logfile) 226 | probe_pbar2 = param["probe_pbar"] + 0.01; 227 | param["probe_pbar"]=probe_pbar2; 228 | end 229 | return param 230 | end 231 | 232 | function SaveStatus_CallBack(it, Nt, S, u0, param) 233 | # -- Save the data for a data set of 1000 -- 234 | if (it*num_probe/Nt > param["probe"]) 235 | param["probe"] += 1; 236 | S["u_probe"][param["probe"],:]=u0[:,1] #* exp(1im*tsim[Int(it)]*Δω_pmp[Int(it)]/tR); 237 | S["detuning"][param["probe"]] = δω_all[ind_sweep[1]][it]; 238 | S["t_sim"][param["probe"]] = t_sim[it] 239 | S["driving_force"][param["probe"],:] = Fdrive(it) 240 | end 241 | return param 242 | end 243 | 244 | function SaveData(S, num_probe, ω0, dω) 245 | # -- need to compute a full spectral κext for 246 | # extraction of the in-cavity power -- 247 | logfile = open(tmp_dir * "log.log" ,"a") 248 | write(logfile,string(Int(round(100))) * "\n") 249 | close(logfile) 250 | 251 | SaveResultsToFile(tmp_dir, S) 252 | end 253 | 254 | function Fdrive(it) 255 | # -- needed to declare it here as we will use it 256 | # later to save it in the dict - 257 | # ------------------------------------------------ 258 | Force = 0 .* exp.(1im.*θ) 259 | 260 | for ii=1:length(fpmp) 261 | # detuning for each pump 262 | # which is i(δωj + Dint[μ = μj]) - iμjθ with μ0 being the center of the 263 | # domain 264 | # The phase shift iμjθ has already been taken into account previously in 265 | # Ain (due to noise, it needs to be initilized throug FFT) 266 | # --------------------------------------------------------------------- 267 | if ii > 1 268 | σ = (2 .* δω_all[ii][it] .+ Dint[μ0+ind_pmp[ii]] .- 0.5.*δω_all[1][it] ) .* t_sim[it] 269 | else 270 | σ = 0 271 | end 272 | Force .= Force .- 1im .* Ain[ii] .*exp(1im .*σ) 273 | end 274 | return Force #.- 1im*Noise() 275 | end 276 | 277 | 278 | tol = 1e-2 279 | maxiter = 10 280 | success = false 281 | 282 | 283 | L½prop = 1im .*zeros(length(μ),1) 284 | L½prop_cpl = 1im .*zeros(length(μ),1) 285 | A_L½prop = 1im .*zeros(length(μ),1) 286 | NL½prop_0 = 1im .*zeros(length(μ),1) 287 | CPL½prop_0 = 1im .*zeros(length(μ),1) 288 | A½prop = 1im .*zeros(length(μ),1) 289 | Aprop = 1im .*zeros(length(μ),1) 290 | NL½prop_1 = 1im .*zeros(length(μ),1) 291 | NLprop = 1im .*zeros(length(μ),1) 292 | Force = 1im .*zeros(length(μ),1) 293 | retL = 1im .*zeros(length(μ),1) 294 | Eout = 1im .*zeros(length(μ),1) 295 | Aout = 1im .*zeros(length(μ),1) 296 | retNL = 1im .*zeros(length(μ),1) 297 | retcpl = 1im .*zeros(length(μ),1) 298 | 299 | function SSFM½step(A0, it, param) 300 | # ---------------------------------------------------------------------------------------- 301 | # Standard split step fourier method 302 | # ∂A/∂t (t, τ)= [L + NL]A + Fdrive 303 | # 304 | # We can first split the equation in two such that: 305 | # and ∂A_l/∂t = L A_l 306 | # and ∂A_Nl/∂t = NL A_nl 307 | # where L and NL are both operators 308 | # 309 | # In the case of the LLE, the linear equation has an obivous solution in the frequency 310 | # domain (time domain more complicated with the derivatife).: 311 | # ^A^_l(t, ω)= exp(^L^ t) 312 | # 313 | # where the ^^ describe the Fourier Transform of the function 314 | # 315 | # After a smal propagation δt the nonlinear term can be expressed as 316 | # A_nl(t +δt , τ) = exp(NL x δt) A 317 | # 318 | # the linear term has an analytical solution in the frequency domain : 319 | # thus we could easily apply this sollution to our problem such that 320 | # ^A^(t + δt, ω) = exp(^L^ x δt)^A^_nl(t, ω) 321 | # 322 | # From here it is easy to get the valye on A with the driving force, which we will 323 | # increment for each δt 324 | # 325 | # A(t + δt, ω) = FFT-1(^A^(t + δt, ω)) + Fdrive x δt 326 | # 327 | # 328 | # However this direct SSF is not the best stable and implementing a 1/2 SSF is much better 329 | # for more information, please checkout G. Agrawal's book (there is litterally the algorithm 330 | # in it) 331 | 332 | 333 | # ---------------------------------------------------------------------------------------- 334 | # G. Moille - 09/08/2022 - NIST/UMD - gmoille@umd.edu 335 | # ---------------------------------------------------------------------------------------- 336 | # -- Define the Linear, Non-Linear and drive Force --- 337 | # Purpose is for easy modification to ad NL or other terms 338 | function FFT_Lin(it) 339 | return -α/2 .+ 1im .* (Dint_shift .- δω_all[1][it] )*tR 340 | end 341 | 342 | function NL(uu, it) 343 | return -1im*( γ*L* abs.(uu).^2 ) 344 | end 345 | 346 | # --- Linear propagation --- 347 | 348 | A0 = A0 .+ Fdrive(Int(it)) .*sqrt(κext) .* dt; 349 | 350 | L½prop .= exp.(FFT_Lin(Int(it)) .* dt/2); 351 | A_L½prop .= ifft_plan* (fft_plan*(A0) .* L½prop); 352 | NL½prop_0 .= NL(A0, it); 353 | A½prop .= A0; 354 | Aprop .= 1im .* zeros(size(A0)); 355 | 356 | # --- iterative procedur to find ^LN^(t + δt, ω) --- 357 | success = false; 358 | for ii in collect(1:maxiter) 359 | err = 0.0 360 | success = false 361 | NL½prop_1 .= NL(A½prop, it); 362 | NLprop .= (NL½prop_0 .+ NL½prop_1) .* dt/2; 363 | Aprop .= ifft_plan*( fft_plan*(A_L½prop .* exp.(NLprop) ) .* L½prop ) 364 | 365 | # --- check if we concerge or not --- 366 | err = LinearAlgebra.norm(Aprop-A½prop,2)/LinearAlgebra.norm(A½prop,2) 367 | if (err < tol) 368 | success = true 369 | break 370 | else 371 | success = false 372 | A½prop .= Aprop 373 | end 374 | end 375 | 376 | if success 377 | u0 = Aprop 378 | return u0 379 | else 380 | print("Convergence Error") 381 | end 382 | end 383 | 384 | function MainSolver(Nt, S, u0) 385 | # Here we are solvint the most general form of the χ(3)-only-LLE 386 | # For full explenation on how to derive this equation (usually from CMT) 387 | # please refere Taheri, H. et al (2017). "Optical lattice trap for Kerr 388 | # solitons" The European Physical Journal D, 71(6) 389 | # 390 | # ∂A/∂t = (-α/2 - iγL |A|² + i TF⁻¹[Dint])A + 391 | # + Σ2 √κextⱼ Fⱼ exp(i σⱼt+ i Dint(η=ηⱼ) - i(ηⱼ-η₀)θ) 392 | # 393 | # where Dint is computer at η0 (i.e. Dint(η0) = 0) 394 | # σⱼ is the detuning between the pump and the closest mode ηⱼ freqeuncy 395 | # and Fⱼ = -i√(Pinⱼ/ħωⱼ) exp(-φⱼ) 396 | # ---------------------------------------------------------------------------------------- 397 | # G. Moille - 04/23/2020 - NIST/UMD - gmoille@umd.edu 398 | # last modification : 05/05/2020 -- Cinquo de Mayo!! 399 | # ---------------------------------------------------------------------------------------- 400 | param = Dict() 401 | 402 | param["tol"] = 1e-3; 403 | param["maxiter"] = 6; 404 | param["step_factor"] = 0.1; 405 | param["probe_pbar"] = parse(Float64,"0.01"); 406 | param["cnt_pbar"] = 0; 407 | param["probe"] = 0; 408 | 409 | loops = collect(1:1:Nt) 410 | 411 | for it in loops 412 | # -- Solve the Split Step Fourier Step -- 413 | # u0 = SSFM(u0, it, param) 414 | u0 = SSFM½step(u0, it, param) 415 | 416 | # -- Update the Progress bar -- 417 | param = ProgressBar_CallBack(Int(it), Nt, S, u0, param) 418 | # -- Save the Data in the dict -- 419 | param = SaveStatus_CallBack(Int(it), Nt, S, u0, param) 420 | end 421 | SaveData(S, num_probe, ω0, dω) 422 | 423 | end 424 | 425 | # -- Start the solver 426 | # ---------------------------------------------------- 427 | logfile = open(tmp_dir * "log.log" ,"w") 428 | write(logfile,string(Int(round(0))) * "\n") 429 | close(logfile) 430 | MainSolver(Nt, S, u0) 431 | -------------------------------------------------------------------------------- /build/lib/pyLLE/__init__.py: -------------------------------------------------------------------------------- 1 | from ._llesolver import LLEsolver 2 | from ._analyzedisp import AnalyzeDisp -------------------------------------------------------------------------------- /build/lib/pyLLE/_analyzedisp.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.interpolate as itp 3 | import scipy.io as io 4 | from scipy import constants as cts 5 | import matplotlib as mpl 6 | import matplotlib.pyplot as plt 7 | from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot 8 | import plotly.graph_objs as go 9 | import ipdb 10 | # backend = mpl.get_backend() 11 | # print(backend) 12 | 13 | class AnalyzeDisp(object): 14 | ''' 15 | Calls to analyze the dispersion of a simulated resonator 16 | Initialization input. Everything is in SI ([]=facultative): 17 | **kwargs 18 | - f_center : pump frequency 19 | - file : .txt file to load 20 | - R : radius of the resonator 21 | - rM_fit .: lower and upper bonds of mode to fit the dispersion 22 | - rM_sim .: lower and upper bonds of the modes to extrapolate for the simulation 23 | - f : matplotlib figure handle 24 | - ax : matplotlib axes handle 25 | - label : list of the string for each plot to be labelled 26 | - plottype : define the type of plot 'all' [defaults], 'sim', 'fit', 'fem', 'ind' 27 | 28 | ''' 29 | 30 | def __init__(self, **kwargs): 31 | cts.c = 299792458 32 | self.dispfile = kwargs.get('file', None) 33 | self.R = kwargs.get('R', 23e-6) 34 | self.f_center = kwargs.get('f_center', None) 35 | self.fpmp = kwargs.get('fpmp', None) 36 | self.D1_manual = kwargs.get('D1_manual', None) 37 | self.rM_fit = kwargs.get('rM_fit', []) 38 | self.rM_sim = kwargs.get('rM_sim', []) 39 | self.debug = kwargs.get('debug', False) 40 | self.plottype = kwargs.get('plottype', 'all') 41 | self._logger = kwargs.get('logger', None) 42 | self.pyType = kwargs.get('pyType', 'normal') 43 | self.fig = kwargs.get('fig', 'normal') 44 | assert type(self.dispfile) is str, 'Please provide a file' 45 | assert len(self.rM_fit) > 1, 'Please the modes to fit' 46 | 47 | def GetDint(self): 48 | ''' 49 | Retrieve the dispersion of a resonator based on the frequency of 50 | resonance and azimuthal mode order. The data are fit using a cubic spline method 51 | 52 | **Output** 53 | - self.PrM_fit: scipy.interpolate object which fitted the data 54 | - self.Dint_fit: fitted integrated dispersion for the simulated mode 55 | - self.neff_pmp: effective index at the pump frequency 56 | - self.ng_pmp: group index at the pump frequency 57 | ''' 58 | 59 | 60 | def getFreqModes(f_center= None): 61 | FSR0 = 1e12*23e-6/self.R 62 | lines = open(self.dispfile,'r').readlines() 63 | self.rM = np.array([float(ll.strip().split(',')[0]) for ll in lines]) 64 | self.rf = np.array([float(ll.strip().split(',')[1]) for ll in lines]) 65 | # -- Find the pumped mode -- 66 | if not f_center: 67 | pmp_ind = np.where(np.abs(self.rf-self.fpmp[0]) < 0.5*FSR0)[0] 68 | assert pmp_ind.size == 1, 'Wavelength not found!' 69 | self.pmp_ind_fit = pmp_ind[0] 70 | else: 71 | pmp_ind = np.where(np.abs(self.rf-f_center) < 0.5*FSR0)[0] 72 | assert pmp_ind.size == 1, 'Wavelength not found!' 73 | return pmp_ind[0] 74 | return self.pmp_ind_fit 75 | 76 | def getGroupIndex(): 77 | # -- Compute the effective/group index -- 78 | L = 2*np.pi*self.R 79 | df = np.gradient(self.rf) 80 | self.neff = self.rM * cts.c/(self.rf*2*np.pi*self.R) 81 | self.neff_pmp = self.neff[self.pmp_ind_fit] 82 | self.ng = cts.c/(df*L) 83 | self.ng_pmp = self.ng[self.pmp_ind_fit] 84 | self.tR = L*self.ng_pmp/cts.c 85 | 86 | def getDispersion(): 87 | # Compute the dispersion 88 | df = np.gradient(self.rf) 89 | d1_vg = np.gradient(self.ng)/cts.c 90 | D = -(self.rf**2/cts.c) * d1_vg/df 91 | self.D = D 92 | 93 | def getIntegratedDisp(ind_pmp): 94 | # -- Compute Dint -- 95 | dm = np.array([-2, -1, 0, 1, 2]) 96 | drf = self.rf - self.rf[self.pmp_ind_fit] 97 | Dfit = np.polyfit(dm, drf[ind_pmp+dm], 2) 98 | self.FSR = Dfit[1] 99 | self.D2 = Dfit[0]*2*np.pi 100 | if not self.D1_manual: 101 | D1 = self.FSR * 2*np.pi 102 | else: 103 | D1 = self.D1_manual 104 | μ = self.rM - self.rM[ind_pmp] 105 | ω = 2*np.pi*self.rf 106 | Dint = ω - (ω[ind_pmp] + D1 * μ) 107 | β2 = -self.ng_pmp/cts.c*(2*Dfit[0])/Dfit[1]**2/2/np.pi 108 | self.μ0 = μ 109 | return μ, Dint, D1 110 | 111 | def fitDintDomain(ind0,ind_master, Dint): 112 | 113 | if self.rM_fit == [None, None]: 114 | μfit = [self.μ0[0], self.μ0[-1]] 115 | shift = 0 116 | else: 117 | μfit = self.rM_fit 118 | shift = ind0 - ind_master 119 | # print(shift) 120 | μfit = [rm-shift for rm in μfit] 121 | # print(μfit) 122 | M = np.arange(ind0+μfit[0], 123 | ind0+μfit[1]+1, 124 | dtype=int) 125 | # print(M) 126 | μselect = np.arange(μfit[0],μfit[1]+1, dtype=int) 127 | assert M[0] >= 0, 'Left range for mode order not correct' 128 | assert M[-1] <= self.rM.size, 'Right range for mode order not correct' 129 | 130 | 131 | # self.PrM_fit = itp.splrep(μfit, Dint2fit) 132 | M2fit = self.rM[M] - self.rM[ind0] 133 | Dint2fit = Dint[M] 134 | fitfun = itp.splrep(M2fit, Dint2fit) 135 | fit_selected = itp.splev(μselect, fitfun) 136 | pmp_ind = np.argwhere(M2fit == 0).flatten()[0] 137 | return fitfun, μselect, fit_selected, pmp_ind 138 | 139 | def doFitSimulationDint(fitfun, ind0, ind_master): 140 | # if self.rM_fit == [None, None]: 141 | # shift = 0 142 | # else: 143 | # μfit = self.rM_fit 144 | shift = ind0 - ind_master 145 | 146 | μ2fit = [rm-shift for rm in self.rM_sim] 147 | ind_sim = np.arange(μ2fit[0], μ2fit[1]+1, dtype=int) 148 | 149 | Dint_fit = itp.splev(ind_sim, fitfun) 150 | 151 | pmp_ind = np.argwhere(ind_sim == 0).flatten()[0] 152 | 153 | return μ2fit, Dint_fit, pmp_ind 154 | 155 | 156 | 157 | # -- Get all parameters that are not relative to the pump mode -- 158 | # ---------------------------------------------------------------------------- 159 | 160 | 161 | self.μsim = [] 162 | self.Dint_fit = [] 163 | self.Dint_sim = [] 164 | self.pmp_ind = [] 165 | self.Dint = [] 166 | self.D1 = [] 167 | self.μsim = [] 168 | self.μfit = [] 169 | self.ind_pmp_sim = [] 170 | self.ind_pmp_fit = [] 171 | # -- Get all parameters that are relative to the pump mode -- 172 | # ---------------------------------------------------------------------------- 173 | # The data collected here are only entended for visulation purpose as the 174 | # integration Dint that is use in pyLLE is computed at the center of the 175 | # domain. For more information, please look at ComputeLLE.jl file (core 176 | # function in Julia of pyLLE) or chekc out Taheri et al. eq 12 177 | cnt_f = 0 178 | for ff in self.fpmp: 179 | if not ff == self.fpmp[0]: 180 | ind_pmp = getFreqModes(f_center= ff) 181 | else: 182 | ind_pmp = getFreqModes() 183 | ind_master = ind_pmp 184 | getGroupIndex() 185 | getDispersion() 186 | 187 | # will do the fit relative to the first pump 188 | μ_, Dint_, D1_ = getIntegratedDisp(ind_pmp) 189 | ff, μfit_, Dint_fit_, pmp_fit_ = fitDintDomain(ind_pmp,ind_master, Dint_) 190 | μsim_, Dint_sim_, pmp_sim_ = doFitSimulationDint(ff, ind_pmp, ind_master) 191 | 192 | self.Dint += [Dint_] 193 | self.Dint_fit += [Dint_fit_] 194 | self.Dint_sim += [Dint_sim_] 195 | self.D1 += [D1_] 196 | self.ind_pmp_sim += [pmp_sim_] 197 | self.ind_pmp_fit += [pmp_fit_] 198 | self.μsim += [μsim_] 199 | self.μfit += [μfit_] 200 | self.fpmp[cnt_f] = self.rf[ind_pmp] 201 | 202 | cnt_f += 1 203 | 204 | ff0 = self.fpmp[0] 205 | # print(μdomain) 206 | ind0 = np.sum(self.μsim[0])/2 207 | # ind1 = np.sum(self.μsim[1])/2 208 | assert ind0 == int(ind0), 'Domain not correct' 209 | ind_center = int(self.pmp_ind_fit + ind0) 210 | 211 | 212 | for ii in range(len(self.fpmp)): 213 | self.pmp_ind += [int(-1*np.sum(self.μsim[ii])/2)] 214 | 215 | 216 | f_center = self.rf[ind_center] 217 | ind_center = getFreqModes(f_center= f_center) 218 | μ_, Dint_, D1_ = getIntegratedDisp(ind_center) 219 | ff, μfit_, Dint_fit_, pmp_fit_ = fitDintDomain(ind_center,ind_center, Dint_) 220 | μsim_, Dint_sim_, pmp_sim_ = doFitSimulationDint(ff, ind_center, ind_center-ind0) 221 | 222 | self.fpmp += [f_center] 223 | self.Dint += [Dint_] 224 | self.Dint_fit += [Dint_fit_] 225 | self.Dint_sim += [Dint_sim_] 226 | self.D1 += [D1_] 227 | self.ind_pmp_sim += [pmp_sim_] 228 | self.ind_pmp_fit += [pmp_fit_] 229 | self.μsim += [μsim_] 230 | self.μfit += [μfit_] 231 | 232 | # μfit = self.μfit[ii] #+ self.ind_pmp_fit[ii] 233 | μsim = self.μsim[ii] #+ self.ind_pmp_sim[ii] 234 | self.freq_fit = self.fpmp[0] + np.arange(μsim[0], μsim[-1]+1)*self.D1[0]/(2*np.pi) 235 | 236 | # dφ = -(drf-(rM-rM[self.pmp_ind_fit])*FSR_p)/FSR_p*2*np.pi 237 | 238 | def DisplayParam(self): 239 | 240 | Info = '-- Dispersion Analysis --\n' 241 | Info += '\tPump index: {}\n'.format(self.pmp_ind_fit) 242 | Info += '\tCenter Pump: {:.3f} THz\n'.format(self.rf[self.pmp_ind_fit]*1e-12) 243 | Info += '\tFSR: {:.2f} GHz\n'.format(self.FSR*1e-9) 244 | Info += '\tD2: {:.2f} MHz\n'.format(self.D2*1e-6) 245 | print(Info) 246 | 247 | if self._logger: 248 | Info += '\t mu_fit: [{:.0f}, {:.0f}]\n'.format(self.rM_fit[0], 249 | self.rM_fit[1]) 250 | Info += '\t mu_sim: [{:.0f}, {:.0f}]\n'.format(self.rM_sim[0], 251 | self.rM_sim[1]) 252 | 253 | self._logger.info('AnalyzeDisp', Info) 254 | 255 | def DisplayPlot(self, display_center= False): 256 | 257 | def PlotJupyter(): 258 | init_notebook_mode(connected=True) 259 | trace = [] 260 | for ii in range(len(self.fpmp)-1): 261 | μfit = self.μfit[ii] #+ self.ind_pmp_fit[ii] 262 | μsim = self.μsim[ii] #+ self.ind_pmp_sim[ii] 263 | dν_fit = np.arange(μfit[0], μfit[-1]+1)*self.D1[0]/(2*np.pi) 264 | dν_sim = np.arange(μsim[0], μsim[-1]+1)*self.D1[0]/(2*np.pi) 265 | ν0 = self.fpmp[ii] 266 | rf = self.rf 267 | rf_fit = (ν0+dν_fit) 268 | rf_sim = (ν0+dν_sim) 269 | 270 | trace += [go.Scatter( 271 | x = rf*1e-12, 272 | y = (self.Dint[0] - self.Dint[0][self.ind_pmp_fit[ii]] )*1e-9/(2*np.pi), 273 | legendgroup = 'Pump #{:.0f}'.format(ii), 274 | mode = 'markers', 275 | name = 'FEM Simulation')] 276 | if self.plottype.lower() == 'all': 277 | 278 | trace += [go.Scatter( 279 | x = rf_fit*1e-12, 280 | y = (self.Dint_fit[0]- self.Dint[0][self.ind_pmp_fit[ii]])*1e-9/(2*np.pi), 281 | line = dict(width = 2, dash = 'dash'), 282 | legendgroup = 'Pump #{:.0f}'.format(ii), 283 | name = 'Fit')] 284 | trace += [go.Scatter( 285 | x = rf_sim*1e-12, 286 | y = (self.Dint_sim[0] - self.Dint[0][self.ind_pmp_fit[ii]])*1e-9/(2*np.pi), 287 | legendgroup = 'Pump #{:.0f}'.format(ii), 288 | mode = 'lines', 289 | name = 'LLE simulation')] 290 | 291 | 292 | if self.plottype.lower() == 'sim': 293 | 294 | trace += [go.Scatter( 295 | x = rf_sim*1e-12, 296 | y = self.Dint_sim[ii]*1e-9/(2*np.pi), 297 | legendgroup = 'Pump #{:.0f}'.format(ii), 298 | mode = 'lines', 299 | name = 'LLE simulation')] 300 | 301 | if self.plottype.lower() == 'fit': 302 | 303 | trace += [go.Scatter( 304 | x = rf_fit*1e-12, 305 | y = self.Dint_fit[ii]*1e-9/(2*np.pi), 306 | line = dict(width = 2, dash = 'dash'), 307 | legendgroup = 'Pump #{:.0f}'.format(ii), 308 | name = 'Fit')] 309 | if self.plottype.lower() == 'fem': 310 | pass 311 | 312 | self.fig = go.FigureWidget(data=trace) 313 | 314 | self.fig.add_hline(y=0, line_width=3,line_color="white", opacity = 1) 315 | 316 | self.fig.update_layout(xaxis = dict(title = 'Frequency (THz)'), 317 | yaxis = dict(title = 'Dint (GHz)')) 318 | 319 | def PlotMatplotlib(): 320 | self.fig, ax = plt.subplots() 321 | for ii in range(len(self.fpmp)-1): 322 | μfit = self.μfit[ii] #+ self.ind_pmp_fit[ii] 323 | μsim = self.μsim[ii] #+ self.ind_pmp_sim[ii] 324 | dν_fit = np.arange(μfit[0], μfit[-1]+1)*self.D1[0]/(2*np.pi) 325 | dν_sim = np.arange(μsim[0], μsim[-1]+1)*self.D1[0]/(2*np.pi) 326 | ν0 = self.fpmp[ii] 327 | rf = self.rf 328 | rf_fit = (ν0+dν_fit) 329 | rf_sim = (ν0+dν_sim) 330 | 331 | ax.plot(rf*1e-12, 332 | self.Dint[ii]*1e-9/(2*np.pi), 333 | 'o',ms= 3, 334 | label = 'FEM Simulation') 335 | 336 | if self.plottype.lower() == 'all': 337 | 338 | ax.plot(rf_fit*1e-12, 339 | self.Dint_fit[ii]*1e-9/(2*np.pi), 340 | '--', 341 | label = 'Fit') 342 | ax.plot(rf_sim*1e-12, 343 | self.Dint_sim[ii]*1e-9/(2*np.pi), 344 | label = 'LLE simulation') 345 | 346 | if self.plottype.lower() == 'sim': 347 | ax.plot(rf_sim*1e-12, 348 | self.Dint_sim[ii]*1e-9/(2*np.pi), 349 | label = 'LLE simulation') 350 | 351 | if self.plottype.lower() == 'fit': 352 | ax.plot(rf_fit*1e-12, 353 | self.Dint_fit[ii]*1e-9/(2*np.pi), 354 | label = 'Fit') 355 | 356 | if not self.pyType == 'jupyter': 357 | PlotMatplotlib() 358 | else: 359 | PlotJupyter() 360 | 361 | return self.fig 362 | # if __name__ == '__main__': 363 | # plt.close('all') 364 | # analyze = AnalyzeDisp(file='TestDispersion.mat', 365 | # lbd_center = 1500e-9, 366 | # rM_fit=[-50, 160], 367 | # debug=True) 368 | # analyze.GetBeta() 369 | -------------------------------------------------------------------------------- /example/DKS_init.csv: -------------------------------------------------------------------------------- 1 | ,DKS_init,det 2 | 0,(0.37206158583426713+0.1119138776201696j),-2555006428.571428 3 | 1,(0.5692583203446117+0.03693041543235093j),-2555006428.571428 4 | 2,(0.7259021330335659-0.03990855563467501j),-2555006428.571428 5 | 3,(0.5630083333298663-0.08423754159279936j),-2555006428.571428 6 | 4,(0.3535492969136973-0.12005707453987133j),-2555006428.571428 7 | 5,(0.4175156782663365-0.029679571202569175j),-2555006428.571428 8 | 6,(0.5810521529990524+0.13917896754730244j),-2555006428.571428 9 | 7,(0.6087093088592449+0.09332323747281757j),-2555006428.571428 10 | 8,(0.5723335513222291-0.15185337431884358j),-2555006428.571428 11 | 9,(0.5260195676248367-0.198454584413554j),-2555006428.571428 12 | 10,(0.42088452940775567+0.020570885423479766j),-2555006428.571428 13 | 11,(0.3971861771719011+0.13448846882540297j),-2555006428.571428 14 | 12,(0.5843261819659551+0.027128334755300212j),-2555006428.571428 15 | 13,(0.7193082794773734-0.07278166981431466j),-2555006428.571428 16 | 14,(0.5471489017959237-0.09198645003547423j),-2555006428.571428 17 | 15,(0.3388321814322324-0.09352333775491474j),-2555006428.571428 18 | 16,(0.41944924199133043-0.008462147470881984j),-2555006428.571428 19 | 17,(0.6073337166670821+0.1314531182439017j),-2555006428.571428 20 | 18,(0.6267127645830118+0.07252126813620194j),-2555006428.571428 21 | 19,(0.5504889235809545-0.16344743237214363j),-2555006428.571428 22 | 20,(0.4951637382754877-0.1930018694649548j),-2555006428.571428 23 | 21,(0.4261291513370476+0.04020148131578177j),-2555006428.571428 24 | 22,(0.4253885521575661+0.15055499952933496j),-2555006428.571428 25 | 23,(0.5957522613182767+0.015012874818866167j),-2555006428.571428 26 | 24,(0.7086239861085282-0.10295109509468285j),-2555006428.571428 27 | 25,(0.5307521364849335-0.09796692262456606j),-2555006428.571428 28 | 26,(0.32657720729902745-0.06473184784516013j),-2555006428.571428 29 | 27,(0.4261347447960116+0.013633127086641689j),-2555006428.571428 30 | 28,(0.6338851491057289+0.11779436831833585j),-2555006428.571428 31 | 29,(0.6386592225024958+0.048429568717916927j),-2555006428.571428 32 | 30,(0.5265201728374941-0.16959658897210864j),-2555006428.571428 33 | 31,(0.46723176713731096-0.1831208884387957j),-2555006428.571428 34 | 32,(0.434148117630246+0.05843774685314062j),-2555006428.571428 35 | 33,(0.455566876219391+0.1626667284733299j),-2555006428.571428 36 | 34,(0.6057374799631093+0.00029487560835851254j),-2555006428.571428 37 | 35,(0.6925414084003532-0.1319250244491993j),-2555006428.571428 38 | 36,(0.512844960836673-0.09951964450807069j),-2555006428.571428 39 | 37,(0.32018574155064794-0.033967895911018335j),-2555006428.571428 40 | 38,(0.4362977546699584+0.03302298980174625j),-2555006428.571428 41 | 39,(0.6580480856582948+0.1005469697531949j),-2555006428.571428 42 | 40,(0.6467146575091693+0.022286838553107154j),-2555006428.571428 43 | 41,(0.5002103399206352-0.17193967139589042j),-2555006428.571428 44 | 42,(0.44201349184281613-0.1676117247383358j),-2555006428.571428 45 | 43,(0.44644392206513805+0.07464075447413131j),-2555006428.571428 46 | 44,(0.4862380623613502+0.16925769611310643j),-2555006428.571428 47 | 45,(0.6129786879575894-0.015540821966136946j),-2555006428.571428 48 | 46,(0.6727583265715574-0.1585413021726467j),-2555006428.571428 49 | 47,(0.4938006887538229-0.09806516532452232j),-2555006428.571428 50 | 48,(0.31858028679639594-0.0007394748938929571j),-2555006428.571428 51 | 49,(0.4517293313715105+0.04954853471840329j),-2555006428.571428 52 | 50,(0.6781826968160859+0.07756960895783428j),-2555006428.571428 53 | 51,(0.6488324952896893-0.0027953394655792583j),-2555006428.571428 54 | 52,(0.4752719744271424-0.1696768984761836j),-2555006428.571428 55 | 53,(0.4193551199313013-0.14986582432080264j),-2555006428.571428 56 | 54,(0.46062202406511726+0.09014021305180911j),-2555006428.571428 57 | 55,(0.5191173099259575+0.17137431837894462j),-2555006428.571428 58 | 56,(0.6173097112583238-0.0348412768411493j),-2555006428.571428 59 | 57,(0.6468173684540012-0.18124387797164027j),-2555006428.571428 60 | 58,(0.47632174763128976-0.09089553934620524j),-2555006428.571428 61 | 59,(0.3238162769759054+0.030945767495812945j),-2555006428.571428 62 | 60,(0.4680292174909912+0.06218064592423443j),-2555006428.571428 63 | 61,(0.6949288060756103+0.05305545186376162j),-2555006428.571428 64 | 62,(0.647589352411114-0.02870761236666132j),-2555006428.571428 65 | 63,(0.44909126425788015-0.16370148777689975j),-2555006428.571428 66 | 64,(0.4003425926185979-0.12731740505204073j),-2555006428.571428 67 | 65,(0.4788501932635195+0.10285340498113628j),-2555006428.571428 68 | 66,(0.5512235921755052+0.1673215827560269j),-2555006428.571428 69 | 67,(0.6176706992519383-0.054636807336508324j),-2555006428.571428 70 | 68,(0.6176279753070427-0.19955749695360422j),-2555006428.571428 71 | 69,(0.46009761105186403-0.07991727060419218j),-2555006428.571428 72 | 70,(0.3350583608350975+0.06169635331860681j),-2555006428.571428 73 | 71,(0.48592868774898135+0.07025256006601927j),-2555006428.571428 74 | 72,(0.7067921077468354+0.0269562105855665j),-2555006428.571428 75 | 73,(0.6434194106343427-0.05366007320581074j),-2555006428.571428 76 | 74,(0.42274614837369306-0.15505285517523906j),-2555006428.571428 77 | 75,(0.38434185793075937-0.09999132543726537j),-2555006428.571428 78 | 76,(0.5022484949796502+0.11290684561538626j),-2555006428.571428 79 | 77,(0.5814792018217783+0.15514238524592963j),-2555006428.571428 80 | 78,(0.6116689122540242-0.07306367654751507j),-2555006428.571428 81 | 79,(0.5882362698927184-0.2110062569909403j),-2555006428.571428 82 | 80,(0.4468997530772487-0.06881344923958516j),-2555006428.571428 83 | 81,(0.34803463058910167+0.09104808633353918j),-2555006428.571428 84 | 82,(0.5071203899102692+0.07742861368113554j),-2555006428.571428 85 | 83,(0.7161167648617457-0.004335135746469602j),-2555006428.571428 86 | 84,(0.6310753304041342-0.07758350659213005j),-2555006428.571428 87 | 85,(0.3987376693907223-0.13825308853139456j),-2555006428.571428 88 | 86,(0.3763344642697889-0.07265744213403434j),-2555006428.571428 89 | 87,(0.5247397354824661+0.11709700690565379j),-2555006428.571428 90 | 88,(0.6085571046165766+0.14132484141073598j),-2555006428.571428 91 | 89,(0.6052492211804066-0.091317674565237j),-2555006428.571428 92 | 90,(0.5553803482971514-0.2201140010009334j),-2555006428.571428 93 | 91,(0.43432517603105325-0.05214515202017509j),-2555006428.571428 94 | 92,(0.3691487019735062+0.11855094679133799j),-2555006428.571428 95 | 93,(0.5284188612631965+0.07715501277364094j),-2555006428.571428 96 | 94,(0.7178220572926165-0.035303985990919634j),-2555006428.571428 97 | 95,(0.6169171735235361-0.09738629949507768j),-2555006428.571428 98 | 96,(0.37768390535087215-0.11958090657052518j),-2555006428.571428 99 | 97,(0.3714327229073065-0.04395532407767706j),-2555006428.571428 100 | 98,(0.5493917382204359+0.11881344499631295j),-2555006428.571428 101 | 99,(0.6337122599509186+0.12167170206304471j),-2555006428.571428 102 | 100,(0.5935245856247521-0.10888446527946007j),-2555006428.571428 103 | 101,(0.5216929267024998-0.2220051861576226j),-2555006428.571428 104 | 102,(0.4263252077724164-0.0338398446586043j),-2555006428.571428 105 | 103,(0.39362432838056055+0.14186171364324213j),-2555006428.571428 106 | 104,(0.5495368869247277+0.07350407899620838j),-2555006428.571428 107 | 105,(0.7146604572127461-0.06711497647542328j),-2555006428.571428 108 | 106,(0.5988923984388071-0.11383607096211769j),-2555006428.571428 109 | 107,(0.3600949680298954-0.09708106802665288j),-2555006428.571428 110 | 108,(0.3715933166227103-0.01524412287405325j),-2555006428.571428 111 | 109,(0.5746993913969335+0.11632526692531568j),-2555006428.571428 112 | 110,(0.6549940060800504+0.0978885349714773j),-2555006428.571428 113 | 111,(0.5783005098609414-0.12428351737667367j),-2555006428.571428 114 | 112,(0.48807396841677503-0.21843128440604537j),-2555006428.571428 115 | 113,(0.42177407956323265-0.013437233106414004j),-2555006428.571428 116 | 114,(0.4226817130430341+0.16084071256258042j),-2555006428.571428 117 | 115,(0.5690020082142127+0.06476898801283307j),-2555006428.571428 118 | 116,(0.7055359078678582-0.09730929646176226j),-2555006428.571428 119 | 117,(0.5793862028026915-0.12634327057658948j),-2555006428.571428 120 | 118,(0.34593601577044847-0.07264821897378945j),-2555006428.571428 121 | 119,(0.3758566734788856+0.013552569679110829j),-2555006428.571428 122 | 120,(0.6010610414281474+0.11012598968720537j),-2555006428.571428 123 | 121,(0.6721112435460218+0.06916584300435814j),-2555006428.571428 124 | 122,(0.5580064963405178-0.13658095692576244j),-2555006428.571428 125 | 123,(0.45678359194644597-0.20742544324893425j),-2555006428.571428 126 | 124,(0.4224347405662764+0.005930379369310546j),-2555006428.571428 127 | 125,(0.4524900267310964+0.1746432754617343j),-2555006428.571428 128 | 126,(0.5872661832470365+0.054165957110524854j),-2555006428.571428 129 | 127,(0.692660724656601-0.127343737132923j),-2555006428.571428 130 | 128,(0.5562383743414522-0.1354274420590528j),-2555006428.571428 131 | 129,(0.33590499424026726-0.043943787669238975j),-2555006428.571428 132 | 130,(0.3868364854825185+0.04039480052538363j),-2555006428.571428 133 | 131,(0.6255010903368614+0.09781006177678216j),-2555006428.571428 134 | 132,(0.6830418972839323+0.03943842965168042j),-2555006428.571428 135 | 133,(0.5367341166507926-0.14507276884606893j),-2555006428.571428 136 | 134,(0.4273269422255274-0.19249766893820972j),-2555006428.571428 137 | 135,(0.42629164667237945+0.026084305582682425j),-2555006428.571428 138 | 136,(0.48518670688002924+0.18354746247654818j),-2555006428.571428 139 | 137,(0.6031186103374871+0.03941107604448469j),-2555006428.571428 140 | 138,(0.6742957677510669-0.1550602081121957j),-2555006428.571428 141 | 139,(0.5318755911576839-0.13950176141416523j),-2555006428.571428 142 | 140,(0.331131526938237-0.01345548688324432j),-2555006428.571428 143 | 141,(0.4024004645027665+0.06435263792127731j),-2555006428.571428 144 | 142,(0.6478235063231129+0.08108442720545786j),-2555006428.571428 145 | 143,(0.6883218528821293+0.008420206869487341j),-2555006428.571428 146 | 144,(0.5138559285325006-0.14917180443781913j),-2555006428.571428 147 | 145,(0.40146488157507776-0.17346627889623004j),-2555006428.571428 148 | 146,(0.43293366181505893+0.045292923473577586j),-2555006428.571428 149 | 147,(0.5195789209949304+0.1884055804007516j),-2555006428.571428 150 | 148,(0.6172116995588484+0.020282286850330355j),-2555006428.571428 151 | 149,(0.6492350108483361-0.18037812203105627j),-2555006428.571428 152 | 150,(0.5072766470561357-0.1363328235875236j),-2555006428.571428 153 | 151,(0.3340477186279388+0.01689161339182247j),-2555006428.571428 154 | 152,(0.420015721360554+0.08286131466879555j),-2555006428.571428 155 | 153,(0.6661175172555893+0.06311471021819373j),-2555006428.571428 156 | 154,(0.6913037203887783-0.022889904611263483j),-2555006428.571428 157 | 155,(0.48854839372677555-0.15228218302572855j),-2555006428.571428 158 | 156,(0.3768371561556807-0.14750840131320028j),-2555006428.571428 159 | 157,(0.44711726727765816+0.06428938636172067j),-2555006428.571428 160 | 158,(0.553842448934953+0.18363125168808137j),-2555006428.571428 161 | 159,(0.6243357452360851+0.0006138067573086514j),-2555006428.571428 162 | 160,(0.6229073352147685-0.1995710513403663j),-2555006428.571428 163 | 161,(0.484107402593085-0.13151580793598164j),-2555006428.571428 164 | 162,(0.33946183058393214+0.0475841837678179j),-2555006428.571428 165 | 163,(0.4422738550470543+0.0996380122498315j),-2555006428.571428 166 | 164,(0.682469390933206+0.03972453024817781j),-2555006428.571428 167 | 165,(0.6866147958725295-0.05433894767194676j),-2555006428.571428 168 | 166,(0.46294262330998676-0.1488998156798009j),-2555006428.571428 169 | 167,(0.35835298085536527-0.11866540325253994j),-2555006428.571428 170 | 168,(0.46394204012614465+0.07997336721598455j),-2555006428.571428 171 | 169,(0.5868151584802339+0.17403654661155515j),-2555006428.571428 172 | 170,(0.6280479146074815-0.020530654083973098j),-2555006428.571428 173 | 171,(0.593281838276306-0.2145274437872735j),-2555006428.571428 174 | 172,(0.4621243399568292-0.12222643858879632j),-2555006428.571428 175 | 173,(0.35010887606707325+0.07762475069793141j),-2555006428.571428 176 | 174,(0.46749087520507343+0.11198621143049839j),-2555006428.571428 177 | 175,(0.6948336535830598+0.01288559638440724j),-2555006428.571428 178 | 176,(0.6758744606270395-0.0843522906733287j),-2555006428.571428 179 | 177,(0.4377989447886854-0.140060834940874j),-2555006428.571428 180 | 178,(0.3460634345799409-0.08736721714335778j),-2555006428.571428 181 | 179,(0.48320685855393863+0.09153145351588515j),-2555006428.571428 182 | 180,(0.6170728003803485+0.16014754605212222j),-2555006428.571428 183 | 181,(0.6290698303843346-0.04216924597673997j),-2555006428.571428 184 | 182,(0.5606560271164428-0.22598113804738246j),-2555006428.571428 185 | 183,(0.4411020797012414-0.10752764174157348j),-2555006428.571428 186 | 184,(0.36759630994488995+0.10654996780977306j),-2555006428.571428 187 | 185,(0.49458562301610876+0.11753360770305288j),-2555006428.571428 188 | 186,(0.7006780299752778-0.015772654060096057j),-2555006428.571428 189 | 187,(0.6611173460230894-0.11018926989446674j),-2555006428.571428 190 | 188,(0.41521545824161704-0.12835283924472812j),-2555006428.571428 191 | 189,(0.33724318306209833-0.05472292670693136j),-2555006428.571428 192 | 190,(0.5056090289921226+0.10154822154680282j),-2555006428.571428 193 | 191,(0.646079587429701+0.13961451353834356j),-2555006428.571428 194 | 192,(0.6237056701998128-0.06440231908786219j),-2555006428.571428 195 | 193,(0.526691813984368-0.2299800062200501j),-2555006428.571428 196 | 194,(0.4245309871194619-0.09000410922845448j),-2555006428.571428 197 | 195,(0.3888134932058625+0.13183886035756787j),-2555006428.571428 198 | 196,(0.5221219756249692+0.11901644519356784j),-2555006428.571428 199 | 197,(0.7025190973887363-0.04601894501904414j),-2555006428.571428 200 | 198,(0.6411292814245558-0.13358334539059308j),-2555006428.571428 201 | 199,(0.3943959549695631-0.1112607811389957j),-2555006428.571428 202 | 200,(0.3354179847557596-0.021700971618149874j),-2555006428.571428 203 | 201,(0.5287998600586923+0.1065584937669169j),-2555006428.571428 204 | 202,(0.6713028503165741+0.11570416224693937j),-2555006428.571428 205 | 203,(0.6150261267320504-0.0865894992757928j),-2555006428.571428 206 | 204,(0.4907119821393691-0.22883170026043734j),-2555006428.571428 207 | 205,(0.411750897471225-0.06810627027473706j),-2555006428.571428 208 | 206,(0.41560218620276507+0.15239364587663476j),-2555006428.571428 209 | 207,(0.5479297373176403+0.11382478185247004j),-2555006428.571428 210 | 208,(0.6980292774798499-0.07543529544408062j),-2555006428.571428 211 | 209,(0.6190929155483625-0.1532598913261448j),-2555006428.571428 212 | 210,(0.3753240999959725-0.09334282859921908j),-2555006428.571428 213 | 211,(0.3367724584700884+0.01212037260173935j),-2555006428.571428 214 | 212,(0.55530671451194+0.10707265558982382j),-2555006428.571428 215 | 213,(0.6907601302161518+0.08287140181160159j),-2555006428.571428 216 | 214,(0.5977260905714724-0.10713178675208747j),-2555006428.571428 217 | 215,(0.4564300269176332-0.22208505296368058j),-2555006428.571428 218 | 216,(0.40195221573275675-0.05067401178322278j),-2555006428.571428 219 | 217,(0.4396496700049099+0.16479032816181877j),-2555006428.571428 220 | 218,(0.5705432324954767+0.10130761431415877j),-2555006428.571428 221 | 219,(0.685623579562552-0.11412937856919439j),-2555006428.571428 222 | 220,(0.5841344748317889-0.17823105261104852j),-2555006428.571428 223 | 221,(0.35221523683718914-0.0797522928354443j),-2555006428.571428 224 | 222,(0.3365737290072896+0.027871296863255218j),-2555006428.571428 225 | 223,(0.565203799385039+0.08158923269185309j),-2555006428.571428 226 | 224,(0.6864229122113867+0.025630780213278873j),-2555006428.571428 227 | 225,(0.5563395823491085-0.15755376740103266j),-2555006428.571428 228 | 226,(0.3916862059339819-0.2528142565920253j),-2555006428.571428 229 | 227,(0.3559807848178865-0.08252013286310582j),-2555006428.571428 230 | 228,(0.4174569867993799+0.10458007547422934j),-2555006428.571428 231 | 229,(0.524097048235467-0.005840299824945023j),-2555006428.571428 232 | 230,(0.5793752518972392-0.2636778384720004j),-2555006428.571428 233 | 231,(0.43553100770918096-0.3424235818820027j),-2555006428.571428 234 | 232,(0.18751038491094404-0.252602715374197j),-2555006428.571428 235 | 233,(0.15005143165259732-0.20052170512302464j),-2555006428.571428 236 | 234,(0.32707591956496296-0.25958605503901194j),-2555006428.571428 237 | 235,(0.3544191680567099-0.4361386371875498j),-2555006428.571428 238 | 236,(0.09238814120895669-0.7224976381063891j),-2555006428.571428 239 | 237,(-0.21524513401849124-0.9451439787249699j),-2555006428.571428 240 | 238,(-0.39329429184652803-0.972325813829885j),-2555006428.571428 241 | 239,(-0.5221646120441555-1.0662262000298046j),-2555006428.571428 242 | 240,(-0.7208221551463843-1.5399715091940778j),-2555006428.571428 243 | 241,(-1.0842338276076715-2.2387335554082277j),-2555006428.571428 244 | 242,(-1.72028575577743-2.846249627081119j),-2555006428.571428 245 | 243,(-2.552993893990332-3.420032584338725j),-2555006428.571428 246 | 244,(-3.323822966630821-4.228204026450047j),-2555006428.571428 247 | 245,(-4.041893865354564-5.363465033244017j),-2555006428.571428 248 | 246,(-5.037927746343297-6.770177641592189j),-2555006428.571428 249 | 247,(-6.335485416614758-8.325142500543427j),-2555006428.571428 250 | 248,(-7.3838852833662445-9.66882033668589j),-2555006428.571428 251 | 249,(-7.5699287279044505-10.225909393838592j),-2555006428.571428 252 | 250,(-6.805180262539682-9.632713019882745j),-2555006428.571428 253 | 251,(-5.607559561933281-8.145990642931075j),-2555006428.571428 254 | 252,(-4.518425829093514-6.551236104698278j),-2555006428.571428 255 | 253,(-3.57787815635194-5.393996256921535j),-2555006428.571428 256 | 254,(-2.7029724290790873-4.448393784012522j),-2555006428.571428 257 | 255,(-2.082666456834556-3.388125325199188j),-2555006428.571428 258 | 256,(-1.721274550655769-2.451296305119334j),-2555006428.571428 259 | 257,(-1.25168583712962-1.887734651130173j),-2555006428.571428 260 | 258,(-0.6447419044024644-1.4935942958604245j),-2555006428.571428 261 | 259,(-0.34017522636398967-1.1364288943382166j),-2555006428.571428 262 | 260,(-0.3739677266180551-0.9402173642489843j),-2555006428.571428 263 | 261,(-0.28093692777271534-0.7901269433187909j),-2555006428.571428 264 | 262,(0.016429745290568117-0.4687592269751713j),-2555006428.571428 265 | 263,(0.1878277008956994-0.2030102976099j),-2555006428.571428 266 | 264,(0.2311933250788891-0.2862732123448762j),-2555006428.571428 267 | 265,(0.3247688248847415-0.43104007718896653j),-2555006428.571428 268 | 266,(0.34020156467924956-0.265374766153338j),-2555006428.571428 269 | 267,(0.23056662158021485-0.02381698962179975j),-2555006428.571428 270 | 268,(0.3021090633531419-0.02823531652668802j),-2555006428.571428 271 | 269,(0.5745419909159717-0.1087547821017153j),-2555006428.571428 272 | 270,(0.6151832364918242-0.09236784450112241j),-2555006428.571428 273 | 271,(0.37142117103662314-0.11345857342528046j),-2555006428.571428 274 | 272,(0.3031780752921863-0.14054658700378592j),-2555006428.571428 275 | 273,(0.49786367729008324+0.009185541072427058j),-2555006428.571428 276 | 274,(0.5893071401405133+0.1421351688888467j),-2555006428.571428 277 | 275,(0.52822632424059-0.025165606163318834j),-2555006428.571428 278 | 276,(0.5253697893864295-0.23051667366794054j),-2555006428.571428 279 | 277,(0.504889130972017-0.10525809314854345j),-2555006428.571428 280 | 278,(0.39107623856071566+0.11581403007661642j),-2555006428.571428 281 | 279,(0.43477095159047+0.07404640499763324j),-2555006428.571428 282 | 280,(0.6627459923001184-0.06392188961499452j),-2555006428.571428 283 | 281,(0.674970327775205-0.06791294671226049j),-2555006428.571428 284 | 282,(0.414133255051906-0.06288064641647362j),-2555006428.571428 285 | 283,(0.33627427683036204-0.08181659293126867j),-2555006428.571428 286 | 284,(0.5421719911079756+0.03413695386256549j),-2555006428.571428 287 | 285,(0.6417749086705343+0.14082650169709393j),-2555006428.571428 288 | 286,(0.5507433143697263-0.024125689696311223j),-2555006428.571428 289 | 287,(0.5102400736566292-0.22374057264903824j),-2555006428.571428 290 | 288,(0.5007175898883589-0.09079223667571479j),-2555006428.571428 291 | 289,(0.4235251645285044+0.14044543086798897j),-2555006428.571428 292 | 290,(0.46474730210867304+0.08462711223361269j),-2555006428.571428 293 | 291,(0.6627593454435642-0.08426076246646151j),-2555006428.571428 294 | 292,(0.6666934669248056-0.08800132348338581j),-2555006428.571428 295 | 293,(0.4097548054078283-0.04847956041905718j),-2555006428.571428 296 | 294,(0.3320917397961412-0.05140586812684616j),-2555006428.571428 297 | 295,(0.5560766131327814+0.03883868986826615j),-2555006428.571428 298 | 296,(0.6697232404915521+0.11851820831917366j),-2555006428.571428 299 | 297,(0.5486867282569554-0.03766643022344658j),-2555006428.571428 300 | 298,(0.4785324959038697-0.2173987918223136j),-2555006428.571428 301 | 299,(0.49069360183090044-0.08032885230827054j),-2555006428.571428 302 | 300,(0.4482373658373452+0.15326460178703635j),-2555006428.571428 303 | 301,(0.485669749556463+0.08991563853458079j),-2555006428.571428 304 | 302,(0.6565833388199976-0.10579577095923968j),-2555006428.571428 305 | 303,(0.6502742256370573-0.11068981774004652j),-2555006428.571428 306 | 304,(0.400834164212525-0.03207085015299592j),-2555006428.571428 307 | 305,(0.332888725655237-0.019494220743288652j),-2555006428.571428 308 | 306,(0.5698363688601973+0.036772000636040955j),-2555006428.571428 309 | 307,(0.6886996715401584+0.09233767836962536j),-2555006428.571428 310 | 308,(0.5441122430582244-0.048286199003067395j),-2555006428.571428 311 | 309,(0.4482279006560616-0.20871579911885363j),-2555006428.571428 312 | 310,(0.4800751534685921-0.06826472244644331j),-2555006428.571428 313 | 311,(0.4752520223508085+0.16405026766354894j),-2555006428.571428 314 | 312,(0.5075339968740974+0.08993115505745695j),-2555006428.571428 315 | 313,(0.6449393124582429-0.12749985098511615j),-2555006428.571428 316 | 314,(0.6298886844298873-0.12838894676773252j),-2555006428.571428 317 | 315,(0.39586963358184635-0.013911274971306075j),-2555006428.571428 318 | 316,(0.33784412710817285+0.010366095355958014j),-2555006428.571428 319 | 317,(0.582977504948477+0.03316660349795474j),-2555006428.571428 320 | 318,(0.7044075649949394+0.0631384949842858j),-2555006428.571428 321 | 319,(0.5359157994800747-0.058555681610807944j),-2555006428.571428 322 | 320,(0.4193513745689738-0.19398588821441326j),-2555006428.571428 323 | 321,(0.47338506569886396-0.05504469016110983j),-2555006428.571428 324 | 322,(0.5030739218121393+0.16996243122410457j),-2555006428.571428 325 | 323,(0.5284684780420948+0.08701152729246353j),-2555006428.571428 326 | 324,(0.6306255708865413-0.14800504986105203j),-2555006428.571428 327 | 325,(0.6061214783257668-0.1429492521567425j),-2555006428.571428 328 | 326,(0.39337063034978464+0.007080649108462292j),-2555006428.571428 329 | 327,(0.3494595768943968+0.038558898601897214j),-2555006428.571428 330 | 328,(0.5947073504600706+0.0249509527798444j),-2555006428.571428 331 | 329,(0.7140033404327859+0.03374091494394163j),-2555006428.571428 332 | 330,(0.5275901515229322-0.06682487249423384j),-2555006428.571428 333 | 331,(0.39214740404293125-0.17671320827097908j),-2555006428.571428 334 | 332,(0.4684595974994008-0.03929892757906001j),-2555006428.571428 335 | 333,(0.5337591009062128+0.1720179820869264j),-2555006428.571428 336 | 334,(0.5479554110537639+0.07845780573544128j),-2555006428.571428 337 | 335,(0.6110439298538324-0.16572987161735547j),-2555006428.571428 338 | 336,(0.5817335569484823-0.15158402247632016j),-2555006428.571428 339 | 337,(0.3952676500504207+0.02741502893772072j),-2555006428.571428 340 | 338,(0.3638566016844669+0.06403489726280404j),-2555006428.571428 341 | 339,(0.6058253308211726+0.015562768051926593j),-2555006428.571428 342 | 340,(0.7195697608723699+0.0022568030858102603j),-2555006428.571428 343 | 341,(0.5162397510403263-0.07343680308185738j),-2555006428.571428 344 | 342,(0.3679967922216439-0.1543340824253117j),-2555006428.571428 345 | 343,(0.4676143358391312-0.023213428858224115j),-2555006428.571428 346 | 344,(0.5646520120606083+0.16868615756453473j),-2555006428.571428 347 | 345,(0.5647277413284573+0.06663043472211895j),-2555006428.571428 348 | 346,(0.5884644101554699-0.1800992105332546j),-2555006428.571428 349 | 347,(0.5568587265936268-0.15571076246486065j),-2555006428.571428 350 | 348,(0.40075251842223697+0.04760660748502336j),-2555006428.571428 351 | 349,(0.38171711582364126+0.08636973630061758j),-2555006428.571428 352 | 350,(0.6155020548240865+0.004390174407378755j),-2555006428.571428 353 | 351,(0.7208255325327406-0.030055257828886777j),-2555006428.571428 354 | 352,(0.5023336055552302-0.07837770704850583j),-2555006428.571428 355 | 353,(0.3471456580150096-0.12668865974234578j),-2555006428.571428 356 | 354,(0.47216416938100014-0.007536609670981221j),-2555006428.571428 357 | 355,(0.5940508650677208+0.15841212110286393j),-2555006428.571428 358 | 356,(0.5770009746464622+0.05374422665891792j),-2555006428.571428 359 | 357,(0.5657401171407249-0.18995944589576447j),-2555006428.571428 360 | 358,(0.5320048975042303-0.1581332725481648j),-2555006428.571428 361 | 359,(0.40695588650619213+0.06858366467691894j),-2555006428.571428 362 | 360,(0.4054624276854917+0.10738439770500054j),-2555006428.571428 363 | 361,(0.6243135101384557-0.012550540716660041j),-2555006428.571428 364 | 362,(0.7130167494314484-0.061443653681992956j),-2555006428.571428 365 | 363,(0.48938360237875456-0.07711826495929741j),-2555006428.571428 366 | 364,(0.33290190257804275-0.09907983260869319j),-2555006428.571428 367 | 365,(0.476542403968101+0.006448710856149743j),-2555006428.571428 368 | 366,(0.6227220439187257+0.14653083520827387j),-2555006428.571428 369 | 367,(0.5885270815630512+0.03694813892991803j),-2555006428.571428 370 | 368,(0.5386917030010365-0.1974605123445591j),-2555006428.571428 371 | 369,(0.5073167146690107-0.15349571439021523j),-2555006428.571428 372 | 370,(0.41924972719603054+0.08817945121835061j),-2555006428.571428 373 | 371,(0.43079931949587197+0.12217505449177518j),-2555006428.571428 374 | 372,(0.6293324888656259-0.029815623011235748j),-2555006428.571428 375 | 373,(0.7017245861111165-0.0909944209368142j),-2555006428.571428 376 | 374,(0.47583506841005585-0.07404170536758721j),-2555006428.571428 377 | 375,(0.32284614119267147-0.06873493952481095j),-2555006428.571428 378 | 376,(0.4843716081920121+0.01912276835714631j),-2555006428.571428 379 | 377,(0.6493316122068084+0.12986404108022123j),-2555006428.571428 380 | 378,(0.5964308074117777+0.018396684337747278j),-2555006428.571428 381 | 379,(0.5099478064267846-0.2006179183838252j),-2555006428.571428 382 | 380,(0.48429872011468883-0.14417695734002195j),-2555006428.571428 383 | 381,(0.435493246774188+0.10591254885927856j),-2555006428.571428 384 | 382,(0.45793577120225726+0.13178576480032458j),-2555006428.571428 385 | 383,(0.6306127991504541-0.048272709617222485j),-2555006428.571428 386 | 384,(0.6862656769784643-0.11734685445639947j),-2555006428.571428 387 | 385,(0.46330959111718273-0.0689843265151486j),-2555006428.571428 388 | 386,(0.3164732556794548-0.03719416448771411j),-2555006428.571428 389 | 387,(0.4954125091416846+0.031233057275753533j),-2555006428.571428 390 | 388,(0.6742643887776625+0.10771616142210941j),-2555006428.571428 391 | 389,(0.5988283553728737-0.0016889838586515262j),-2555006428.571428 392 | 390,(0.4805362810796085-0.19734291662318582j),-2555006428.571428 393 | 391,(0.4653628728729393-0.13153019067062013j),-2555006428.571428 394 | 392,(0.45387657274565296+0.11971141706997078j),-2555006428.571428 395 | 393,(0.48502748766554454+0.13814107447896612j),-2555006428.571428 396 | 394,(0.6306190029283106-0.0671824031792928j),-2555006428.571428 397 | 395,(0.6659811081078371-0.14269777707234418j),-2555006428.571428 398 | 396,(0.4500823429695014-0.059483664792812446j),-2555006428.571428 399 | 397,(0.31740365539282606-0.004333679186116515j),-2555006428.571428 400 | 398,(0.5086075897772195+0.038777838952541416j),-2555006428.571428 401 | 399,(0.6939603285640952+0.08246666715738428j),-2555006428.571428 402 | 400,(0.5983129578477495-0.02071570229306016j),-2555006428.571428 403 | 401,(0.4520067095463929-0.19051743823682163j),-2555006428.571428 404 | 402,(0.44813097222915954-0.11576711825661756j),-2555006428.571428 405 | 403,(0.47536505679930846+0.13171261235899231j),-2555006428.571428 406 | 404,(0.5132314635785838+0.13879378036465626j),-2555006428.571428 407 | 405,(0.6261214914694802-0.08676679344344655j),-2555006428.571428 408 | 406,(0.6420676896198954-0.16336287517251744j),-2555006428.571428 409 | 407,(0.43894457614473-0.04751724246039321j),-2555006428.571428 410 | 408,(0.3234425692078676+0.02798246338806062j),-2555006428.571428 411 | 409,(0.5234437250185769+0.043317079372708706j),-2555006428.571428 412 | 410,(0.709244500340017+0.0541997704635718j),-2555006428.571428 413 | 411,(0.5942085773429728-0.039042800704421524j),-2555006428.571428 414 | 412,(0.42427008105991-0.1791189383038699j),-2555006428.571428 415 | 413,(0.4345961107345125-0.09702286345017962j),-2555006428.571428 416 | 414,(0.49913550539049795+0.13971625683119815j),-2555006428.571428 417 | 415,(0.5403561276881994+0.13507309066245943j),-2555006428.571428 418 | 416,(0.6189056483807256-0.10600359365098962j),-2555006428.571428 419 | 417,(0.6143934309734765-0.18051241136732296j),-2555006428.571428 420 | 418,(0.4295598567757411-0.03169678720816134j),-2555006428.571428 421 | 419,(0.33632037913035207+0.05866882167939983j),-2555006428.571428 422 | 420,(0.5383063015911086+0.043130711344097766j),-2555006428.571428 423 | 421,(0.7186956006028347+0.02498725000503094j),-2555006428.571428 424 | 422,(0.588276639730771-0.05537573899512918j),-2555006428.571428 425 | 423,(0.39836454340095107-0.16525011703427686j),-2555006428.571428 426 | 424,(0.4227520500303858-0.07545495998511409j),-2555006428.571428 427 | 425,(0.5264451292842922+0.14576429284267323j),-2555006428.571428 428 | 426,(0.567210927157952+0.12388676278400779j),-2555006428.571428 429 | 427,(0.604794594350757-0.12417303015395695j),-2555006428.571428 430 | 428,(0.585865643798836-0.18960044797074505j),-2555006428.571428 431 | 429,(0.4253675039612363-0.016339960002249986j),-2555006428.571428 432 | 430,(0.3508718673688087+0.08576365627403998j),-2555006428.571428 433 | 431,(0.5534352373859598+0.0430560999416683j),-2555006428.571428 434 | 432,(0.7263228989571033-0.0070795222314592775j),-2555006428.571428 435 | 433,(0.5766127537250176-0.07230789668518067j),-2555006428.571428 436 | 434,(0.37346259915804336-0.14376769858212032j),-2555006428.571428 437 | 435,(0.41890746892670283-0.052427566330589745j),-2555006428.571428 438 | 436,(0.5535084889652786+0.14389664446783454j),-2555006428.571428 439 | 437,(0.5889682189418584+0.11091028678902626j),-2555006428.571428 440 | 438,(0.5905550865021661-0.13907229368833995j),-2555006428.571428 441 | 439,(0.5560744536845618-0.19694591108167128j),-2555006428.571428 442 | 440,(0.4213512088475953+0.0017634170086536442j),-2555006428.571428 443 | -------------------------------------------------------------------------------- /example/RW1000_H430.csv: -------------------------------------------------------------------------------- 1 | 100.0,147175373487810.78 2 | 101.0,148354155056151.7 3 | 102.0,149520349841128.25 4 | 103.0,150674023381121.16 5 | 104.0,151815614065231.38 6 | 105.0,152945778693445.75 7 | 106.0,154065253673407.2 8 | 107.0,155174769865701.1 9 | 108.0,156275017038684.4 10 | 109.0,157366641902143.06 11 | 110.0,158450264476418.2 12 | 111.0,159526502422125.4 13 | 112.0,160595995709968.5 14 | 113.0,161659422420511.84 15 | 114.0,162717492517312.06 16 | 115.0,163770907687168.5 17 | 116.0,164820290764807.94 18 | 117.0,165866113606020.28 19 | 118.0,166908663279574.72 20 | 119.0,167948065377074.16 21 | 120.0,168984347770941.3 22 | 121.0,170017510492493.12 23 | 122.0,171047575590260.94 24 | 123.0,172074609306058.1 25 | 124.0,173098722429468.72 26 | 125.0,174120059092258.8 27 | 126.0,175138782552204.94 28 | 127.0,176155062844450.03 29 | 128.0,177169068044267.25 30 | 129.0,178180959016161.66 31 | 130.0,179190886740121.78 32 | 131.0,180198991223532.1 33 | 132.0,181205401283754.16 34 | 133.0,182210234826335.7 35 | 134.0,183213599453164.62 36 | 135.0,184215593291933.75 37 | 136.0,185216305933692.03 38 | 137.0,186215819373937.97 39 | 138.0,187214208885823.7 40 | 139.0,188211543791909.7 41 | 140.0,189207888128345.28 42 | 141.0,190203301209723.5 43 | 142.0,191197838108108.25 44 | 143.0,192191550060550.72 45 | 144.0,193184484819735.6 46 | 145.0,194176686965590.03 47 | 146.0,195168198206066.62 48 | 147.0,196159057716315.72 49 | 148.0,197149302586530.16 50 | 149.0,198138968403776.72 51 | 150.0,199128089738269.12 52 | 151.0,200116699904791.2 53 | 152.0,201104829692721.28 54 | 153.0,202092506275370.0 55 | 154.0,203079753760496.1 56 | 155.0,204066594695329.75 57 | 156.0,205053051003706.25 58 | 157.0,206039144099732.1 59 | 158.0,207024894687118.62 60 | 159.0,208010322586305.2 61 | 160.0,208995446661082.8 62 | 161.0,209980284816128.9 63 | 162.0,210964854030023.03 64 | 163.0,211949170402005.72 65 | 164.0,212933249201856.62 66 | 165.0,213917104918418.0 67 | 166.0,214900751305148.4 68 | 167.0,215884201422344.4 69 | 168.0,216867467676137.88 70 | 169.0,217850561854548.4 71 | 170.0,218833495160876.56 72 | 171.0,219816278244728.1 73 | 172.0,220798921230906.25 74 | 173.0,221781433746382.28 75 | 174.0,222763824945528.62 76 | 175.0,223746103533769.5 77 | 176.0,224728277789781.3 78 | 177.0,225710355586362.4 79 | 178.0,226692344410080.38 80 | 179.0,227674251379781.25 81 | 180.0,228656083264053.6 82 | 181.0,229637846497713.03 83 | 182.0,230619547197380.25 84 | 183.0,231601191176212.25 85 | 184.0,232582783957844.72 86 | 185.0,233564330789591.03 87 | 186.0,234545836654953.2 88 | 187.0,235527306285481.7 89 | 188.0,236508744172028.1 90 | 189.0,237490154575423.38 91 | 190.0,238471541536622.25 92 | 191.0,239452908886337.2 93 | 192.0,240434260254201.44 94 | 193.0,241415599077478.28 95 | 194.0,242396928609350.1 96 | 195.0,243378251926807.44 97 | 196.0,244359571938160.88 98 | 197.0,245340891390195.5 99 | 198.0,246322212874989.97 100 | 199.0,247303538836416.88 101 | 200.0,248284871576340.6 102 | 201.0,249266213260531.25 103 | 202.0,250247565924304.88 104 | 203.0,251228931477911.6 105 | 204.0,252210311711677.6 106 | 205.0,253191708300917.03 107 | 206.0,254173122810626.1 108 | 207.0,255154556699967.47 109 | 208.0,256136011326559.2 110 | 209.0,257117487950574.1 111 | 210.0,258098987738662.0 112 | 211.0,259080511767703.1 113 | 212.0,260062061028396.38 114 | 213.0,261043636428699.7 115 | 214.0,262025238797119.47 116 | 215.0,263006868885861.72 117 | 216.0,263988527373854.0 118 | 217.0,264970214869634.8 119 | 218.0,265951931914128.56 120 | 219.0,266933678983301.03 121 | 220.0,267915456490709.2 122 | 221.0,268897264789942.6 123 | 222.0,269879104176967.0 124 | 223.0,270860974892373.97 125 | 224.0,271842877123535.88 126 | 225.0,272824811006677.97 127 | 226.0,273806776628864.88 128 | 227.0,274788774029908.1 129 | 228.0,275770803204198.5 130 | 229.0,276752864102466.2 131 | 230.0,277734956633469.47 132 | 231.0,278717080665619.9 133 | 232.0,279699236028541.84 134 | 233.0,280681422514572.3 135 | 234.0,281663639880202.0 136 | 235.0,282645887847461.94 137 | 236.0,283628166105255.25 138 | 237.0,284610474310637.6 139 | 238.0,285592812090051.0 140 | 239.0,286575179040509.06 141 | 240.0,287557574730736.4 142 | 241.0,288539998702266.94 143 | 242.0,289522450470500.75 144 | 243.0,290504929525717.7 145 | 244.0,291487435334060.0 146 | 245.0,292469967338470.75 147 | 246.0,293452524959602.7 148 | 247.0,294435107596690.44 149 | 248.0,295417714628394.0 150 | 249.0,296400345413604.94 151 | 250.0,297382999292230.94 152 | 251.0,298365675585946.2 153 | 252.0,299348373598915.06 154 | 253.0,300331092618491.1 155 | 254.0,301313831915890.25 156 | 255.0,302296590746839.25 157 | 256.0,303279368352199.44 158 | 257.0,304262163958571.6 159 | 258.0,305244976778875.44 160 | 259.0,306227806012911.06 161 | 260.0,307210650847897.8 162 | 261.0,308193510458996.7 163 | 262.0,309176384009812.7 164 | 263.0,310159270652878.44 165 | 264.0,311142169530123.4 166 | 265.0,312125079773323.6 167 | 266.0,313108000504539.2 168 | 267.0,314090930836531.1 169 | 268.0,315073869873169.6 170 | 269.0,316056816709822.7 171 | 270.0,317039770433736.3 172 | 271.0,318022730124396.25 173 | 272.0,319005694853881.2 174 | 273.0,319988663687202.9 175 | 274.0,320971635682631.0 176 | 275.0,321954609892013.1 177 | 276.0,322937585361077.9 178 | 277.0,323920561129730.6 179 | 278.0,324903536232339.06 180 | 279.0,325886509698006.25 181 | 280.0,326869480550838.9 182 | 281.0,327852447810201.2 183 | 282.0,328835410490964.9 184 | 283.0,329818367603747.6 185 | 284.0,330801318155142.94 186 | 285.0,331784261147945.75 187 | 286.0,332767195581366.44 188 | 287.0,333750120451239.75 189 | 288.0,334733034750225.8 190 | 289.0,335715937468004.7 191 | 290.0,336698827591463.6 192 | 291.0,337681704104880.5 193 | 292.0,338664565990096.2 194 | 293.0,339647412226686.2 195 | 294.0,340630241792123.7 196 | 295.0,341613053661937.4 197 | 296.0,342595846809864.06 198 | 297.0,343578620207996.94 199 | 298.0,344561372826928.06 200 | 299.0,345544103635885.44 201 | 300.0,346526811602867.44 202 | 301.0,347509495694770.3 203 | 302.0,348492154877513.3 204 | 303.0,349474788116157.6 205 | 304.0,350457394375024.25 206 | 305.0,351439972617805.06 207 | 306.0,352422521807670.2 208 | 307.0,353405040907374.44 209 | 308.0,354387528879358.3 210 | 309.0,355369984685844.06 211 | 310.0,356352407288931.3 212 | 311.0,357334795650688.75 213 | 312.0,358317148733241.0 214 | 313.0,359299465498853.9 215 | 314.0,360281744910017.6 216 | 315.0,361263985929525.5 217 | 316.0,362246187520550.2 218 | 317.0,363228348646718.5 219 | 318.0,364210468272182.56 220 | 319.0,365192545361689.1 221 | 320.0,366174578880645.06 222 | 321.0,367156567795184.4 223 | 322.0,368138511072227.75 224 | 323.0,369120407679543.5 225 | 324.0,370102256585805.6 226 | 325.0,371084056760649.44 227 | 326.0,372065807174726.2 228 | 327.0,373047506799754.06 229 | 328.0,374029154608569.6 230 | 329.0,375010749575174.5 231 | 330.0,375992290674784.9 232 | 331.0,376973776883873.5 233 | 332.0,377955207180214.8 234 | 333.0,378936580542927.75 235 | 334.0,379917895952514.2 236 | 335.0,380899152390898.6 237 | 336.0,381880348841466.4 238 | 337.0,382861484289099.75 239 | 338.0,383842557720211.0 240 | 339.0,384823568122778.9 241 | 340.0,385804514486378.3 242 | 341.0,386785395802213.06 243 | 342.0,387766211063145.25 244 | 343.0,388746959263724.2 245 | 344.0,389727639400214.3 246 | 345.0,390708250470620.8 247 | 346.0,391688791474717.06 248 | 347.0,392669261414067.4 249 | 348.0,393649659292053.06 250 | 349.0,394629984113892.5 251 | 350.0,395610234886664.06 252 | 351.0,396590410619328.4 253 | 352.0,397570510322746.6 254 | 353.0,398550533009700.5 255 | 354.0,399530477694911.4 256 | 355.0,400510343395056.9 257 | 356.0,401490129128788.5 258 | 357.0,402469833916747.9 259 | 358.0,403449456781581.94 260 | 359.0,404428996747958.7 261 | 360.0,405408452842580.4 262 | 361.0,406387824094197.7 263 | 362.0,407367109533622.5 264 | 363.0,408346308193740.0 265 | 364.0,409325419109520.94 266 | 365.0,410304441318032.6 267 | 366.0,411283373858450.1 268 | 367.0,412262215772064.5 269 | 368.0,413240966102295.0 270 | 369.0,414219623894696.7 271 | 370.0,415198188196969.0 272 | 371.0,416176658058964.5 273 | 372.0,417155032532696.7 274 | 373.0,418133310672346.0 275 | 374.0,419111491534269.06 276 | 375.0,420089574177002.3 277 | 376.0,421067557661270.4 278 | 377.0,422045441049990.8 279 | 378.0,423023223408278.56 280 | 379.0,424000903803452.8 281 | 380.0,424978481305038.9 282 | 381.0,425955954984776.0 283 | 382.0,426933323916617.75 284 | 383.0,427910587176737.6 285 | 384.0,428887743843531.6 286 | 385.0,429864792997621.6 287 | 386.0,430841733721858.1 288 | 387.0,431818565101321.4 289 | 388.0,432795286223325.1 290 | 389.0,433771896177417.94 291 | 390.0,434748394055384.8 292 | 391.0,435724778951247.1 293 | 392.0,436701049961266.6 294 | 393.0,437677206183944.25 295 | 394.0,438653246720020.6 296 | 395.0,439629170672478.0 297 | 396.0,440604977146538.8 298 | 397.0,441580665249666.9 299 | 398.0,442556234091567.4 300 | 399.0,443531682784184.9 301 | 400.0,444507010441704.56 302 | 401.0,445482216180550.3 303 | 402.0,446457299119385.06 304 | 403.0,447432258379107.75 305 | 404.0,448407093082854.4 306 | 405.0,449381802355995.1 307 | 406.0,450356385326132.8 308 | 407.0,451330841123101.75 309 | 408.0,452305168878965.75 310 | 409.0,453279367728016.8 311 | 410.0,454253436806770.8 312 | 411.0,455227375253967.8 313 | 412.0,456201182210568.56 314 | 413.0,457174856819751.6 315 | 414.0,458148398226911.6 316 | 415.0,459121805579656.06 317 | 416.0,460095078027802.5 318 | 417.0,461068214723375.75 319 | 418.0,462041214820604.8 320 | 419.0,463014077475919.25 321 | 420.0,463986801847947.0 322 | 421.0,464959387097510.4 323 | 422.0,465931832387622.6 324 | 423.0,466904136883484.6 325 | 424.0,467876299752480.94 326 | 425.0,468848320164177.0 327 | 426.0,469820197290314.5 328 | 427.0,470791930304808.1 329 | 428.0,471763518383741.06 330 | 429.0,472734960705362.06 331 | 430.0,473706256450080.2 332 | 431.0,474677404800462.2 333 | 432.0,475648404941226.7 334 | 433.0,476619256059241.4 335 | 434.0,477589957343517.8 336 | 435.0,478560507985207.75 337 | 436.0,479530907177598.4 338 | 437.0,480501154116108.8 339 | 438.0,481471247998283.6 340 | 439.0,482441188023790.2 341 | 440.0,483410973394413.7 342 | 441.0,484380603314052.25 343 | 442.0,485350076988711.6 344 | 443.0,486319393626502.06 345 | 444.0,487288552437633.06 346 | 445.0,488257552634407.3 347 | 446.0,489226393431217.4 348 | 447.0,490195074044540.9 349 | 448.0,491163593692934.06 350 | 449.0,492131951597028.9 351 | 450.0,493100146979526.6 352 | 451.0,494068179065194.4 353 | 452.0,495036047080858.0 354 | 453.0,496003750255398.56 355 | 454.0,496971287819747.7 356 | 455.0,497938659006881.75 357 | 456.0,498905863051816.25 358 | 457.0,499872899191601.25 359 | 458.0,500839766665317.7 360 | 459.0,501806464714069.75 361 | 460.0,502772992580980.56 362 | 461.0,503739349511188.5 363 | 462.0,504705534751840.4 364 | 463.0,505671547552086.2 365 | 464.0,506637387163075.1 366 | 465.0,507603052837948.8 367 | 466.0,508568543831837.7 368 | 467.0,509533859401854.4 369 | 468.0,510498998807089.06 370 | 469.0,511463961308604.0 371 | 470.0,512428746169428.9 372 | 471.0,513393352654554.2 373 | 472.0,514357780030926.8 374 | 473.0,515322027567445.4 375 | 474.0,516286094534953.1 376 | 475.0,517249980206234.3 377 | 476.0,518213683856007.9 378 | 477.0,519177204760922.3 379 | 478.0,520140542199550.6 380 | 479.0,521103695452384.25 381 | 480.0,522066663801829.44 382 | 481.0,523029446532199.2 383 | 482.0,523992042929710.2 384 | 483.0,524954452282476.5 385 | 484.0,525916673880504.2 386 | 485.0,526878707015686.8 387 | 486.0,527840550981798.2 388 | 487.0,528802205074489.4 389 | 488.0,529763668591281.2 390 | 489.0,530724940831560.5 391 | 490.0,531686021096574.06 392 | 491.0,532646908689423.1 393 | 492.0,533607602915058.0 394 | 493.0,534568103080273.4 395 | 494.0,535528408493702.56 396 | 495.0,536488518465811.6 397 | 496.0,537448432308894.8 398 | 497.0,538408149337069.25 399 | 498.0,539367668866268.8 400 | 499.0,540326990214239.4 401 | 500.0,541286112700534.0 402 | 501.0,542245035646505.94 403 | 502.0,543203758375305.2 404 | 503.0,544162280211872.0 405 | 504.0,545120600482932.5 406 | 505.0,546078718516991.8 407 | 506.0,547036633644330.9 408 | 507.0,547994345196999.75 409 | 508.0,548951852508812.2 410 | 509.0,549909154915341.6 411 | 510.0,550866251753914.2 412 | 511.0,551823142363605.7 413 | 512.0,552779826085233.94 414 | 513.0,553736302261355.3 415 | 514.0,554692570236258.4 416 | 515.0,555648629355959.4 417 | 516.0,556604478968197.3 418 | 517.0,557560118422427.1 419 | 518.0,558515547069816.5 420 | 519.0,559470764263239.1 421 | 520.0,560425769357270.8 422 | 521.0,561380561708183.2 423 | 522.0,562335140673938.9 424 | 523.0,563289505614187.0 425 | 524.0,564243655890257.4 426 | 525.0,565197590865155.1 427 | 526.0,566151309903556.5 428 | 527.0,567104812371802.4 429 | 528.0,568058097637895.5 430 | 529.0,569011165071492.2 431 | 530.0,569964014043900.1 432 | 531.0,570916643928071.9 433 | 532.0,571869054098599.5 434 | 533.0,572821243931711.2 435 | 534.0,573773212805263.8 436 | 535.0,574724960098740.5 437 | 536.0,575676485193243.8 438 | 537.0,576627787471490.2 439 | 538.0,577578866317808.1 440 | 539.0,578529721118129.5 441 | 540.0,579480351259986.9 442 | 541.0,580430756132507.4 443 | 542.0,581380935126409.0 444 | 543.0,582330887633994.4 445 | 544.0,583280613049146.4 446 | 545.0,584230110767323.5 447 | 546.0,585179380185554.6 448 | 547.0,586128420702434.0 449 | 548.0,587077231718117.1 450 | 549.0,588025812634314.5 451 | -------------------------------------------------------------------------------- /images/NISTlogo32x32.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregmoille/pyLLE/cafb3ccde447a678822ff3545c30c32d09ee7626/images/NISTlogo32x32.jpg -------------------------------------------------------------------------------- /licence.txt: -------------------------------------------------------------------------------- 1 | This software was developed at the National Institute of Standards and Technology (NIST) by employees of the Federal Government in the course of their official duties. 2 | Pursuant to title 17 Section 105 of the United States Code this software is not subject to copyright protection and is in the public domain. 3 | _pyLLE_ is an experimental system. NIST assumes no responsibility whatsoever for its use by other parties, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic. 4 | We would appreciate acknowledgment if the software is used. This software can be redistributed and/or modified freely provided that any derivative works bear some notice that they are derived from it, and any modified versions bear some notice that they have been modified. 5 | -------------------------------------------------------------------------------- /pyLLE/ComputeLLE.jl: -------------------------------------------------------------------------------- 1 | using HDF5 2 | using Base 3 | using FFTW 4 | using LinearAlgebra 5 | 6 | function Loadh5Param(dir) 7 | h5file = dir * "ParamLLEJulia.h5" 8 | res = Dict() 9 | sim = Dict() 10 | sim_name = ["res", "sim"] 11 | par = [["Qc", "R", "ng", "Qi", "gamma","dispfile"], ["Pin", "Tscan", "domega_init", "domega_end", "domega_stop", "domega", "f_pmp", "mu_sim_center", "ind_pmp", "Dint", "ind_pump_sweep","f_center", "phi_pmp", "D1", "DKSinit_imag","DKSinit_real", "num_probe"]] 12 | cnt = 1 13 | for sim_par = [res, sim] 14 | for it = par[cnt] 15 | sim_par[it] = h5read(h5file, sim_name[cnt] *"/" * it) 16 | end 17 | cnt += 1 18 | end 19 | 20 | return res, sim 21 | end 22 | 23 | 24 | function SaveResultsToFile(dir, S) 25 | h5file = dir * "ResultsJulia.h5" 26 | println(h5file) 27 | println("\n") 28 | sleep(1) 29 | 30 | h5open(h5file, "w") do file 31 | g = create_group(file, "Results") # create a group 32 | for ii in S 33 | print(ii[1]) 34 | print("\n") 35 | g[ii[1]*"Real"] = real(ii[2]) # create a scalar dataset inside the group 36 | g[ii[1]*"Imag"] = imag(ii[2]) 37 | end 38 | # attrs(g)["Description"] = "This group contains only a single dataset" 39 | end 40 | end 41 | 42 | # ---------------------------------------------------- 43 | # -- STARTING MAIN SCRIPT -- 44 | # ---------------------------------------------------- 45 | tmp_dir = ARGS[1] #"/var/folders/_v/2zfybdtj589c1fwk78q_q5qr0000gn/T/tmpqmatmei5" # 46 | tol = parse(Float64,ARGS[2]) #1e-3 # 47 | maxiter = parse(Int,ARGS[3]) #10 # 48 | stepFactor = parse(Float64,ARGS[4]) #1# 49 | 50 | # tmp_dir = "/tmp/tmpbyi6lbwx" 51 | res, sim = Loadh5Param(tmp_dir) 52 | logfile = open(tmp_dir * "Log.log" ,"w") 53 | 54 | # ---------------------------------------------------- 55 | # -- Collect Data --- 56 | # ---------------------------------------------------- 57 | c0 = 299792458 58 | ħ = 6.634e-34/2/pi 59 | 60 | # -- res parameters -- 61 | ng = res["ng"][1] 62 | R = res["R"][1] 63 | γ = res["gamma"][1] 64 | L = 2*pi*R 65 | 66 | Q0 = res["Qi"][1] 67 | Qc = res["Qc"][1] 68 | fpmp = sim["f_pmp"] 69 | Ppmp = sim["Pin"] 70 | φpmp = sim["phi_pmp"] 71 | num_probe = sim["num_probe"][1] 72 | fcenter= sim["f_center"][1] 73 | 74 | DKSinit_real = sim["DKSinit_real"] 75 | DKSinit_imag = sim["DKSinit_imag"] 76 | 77 | DKSinit = DKSinit_real .+ 1im .* DKSinit_imag 78 | 79 | D1= sim["D1"][1] 80 | FSR = D1/2π 81 | ω0 = 2π*fpmp 82 | ωcenter = 2π*fcenter 83 | 84 | # -- Setup the different Parameters -- 85 | # ---------------------------------------------------- 86 | tR = 1/FSR 87 | T = 1*tR 88 | κext = ω0[1]/Qc*tR 89 | κ0 = ω0[1]/Q0*tR 90 | α = κ0 + κext 91 | # -- Retrieve sim parameters -- 92 | # ---------------------------------------------------- 93 | # debug = Bool(sim["debug"][1]) 94 | δω_init = sim["domega_init"][1] 95 | δω_end = sim["domega_end"][1] 96 | δω_stop = sim["domega_stop"][1] 97 | ind_sweep = sim["ind_pump_sweep"] .+ 1 #because of 0 and 1 index start difference between Julia nd pyhton 98 | t_end = sim["Tscan"][1] 99 | Dint = sim["Dint"] 100 | 101 | 102 | δω = sim["domega"] 103 | ind_pmp = [ii+1 for ii in sim["ind_pmp"]] #because of 0 and 1 index start difference between Julia 104 | μ_sim = sim["mu_sim_center"] 105 | μ = collect(μ_sim[1]:μ_sim[2]) 106 | μ0 = Int(1 + (length(μ)-1)/2) # center of the domain 107 | 108 | # -- Losses -- 109 | # ---------------------------------------------------- 110 | dω = collect(μ_sim[1]:μ_sim[end])*2*pi*FSR 111 | dω_pmp1 = collect(μ_sim[1]-ind_pmp[1]-1:μ_sim[end]-ind_pmp[1]-1)*2*pi*FSR 112 | ω1 = ω0[1] .+ dω_pmp1 113 | 114 | # Make sure there is no residue in the center of the domain 115 | Dint= (Dint .- Dint[μ0]) 116 | # dφ_Kerr=κext*Pin*γ*L/α^2 117 | 118 | Ptot = 0 119 | for ii=1:length(fpmp) 120 | global Ptot += Ppmp[ii] 121 | end 122 | # dt=0.2/(sqrt(Ptot)) 123 | dt = 1 124 | t_end = t_end*tR 125 | t_ramp = t_end 126 | 127 | # -- Sim length -- 128 | # ---------------------------------------------------- 129 | Nt = round(t_ramp/tR/dt) 130 | t1 = 0 131 | 132 | # -- Angle through the resonator -- 133 | # ---------------------------------------------------- 134 | θ = Array(range(0,stop=2π,length=length(μ))) 135 | # -- Time scale --- 136 | # Here the normaizatiton of time is such that 137 | # t=0 when the pump is align with the cold cavity 138 | # δω=0 → t=0- 139 | # hence we need to rescale if the detuning is not symmetric 140 | # ---------------------------------------------------- 141 | δωtot = (abs(δω_end) + abs(δω_init)) 142 | δωcent_perc = -1*sign(δω_end+δω_init)*(abs(δω_end + δω_init)/2)/δωtot 143 | t_sim = Array(range(-t_ramp/2 + δωcent_perc*t_ramp, 144 | stop = t_ramp/2 + δωcent_perc*t_ramp, 145 | length=Int(Nt))) 146 | 147 | # -- Frequency sweep --- 148 | # index = 1 will always be the main pump, i.e. from where the Dint is defined 149 | # δω_init = δω_init * tR 150 | # δω_end = δω_end * tR 151 | # ---------------------------------------------------- 152 | xx = collect(1:Nt) 153 | 154 | δω_all = [δω[ii]*ones(Int(Nt),1) for ii in collect(1:length(fpmp))] 155 | # define which thing we are actually sweeping 156 | for ii in ind_sweep 157 | δω_all[ii][:] = δω_init.+ xx/Nt * (δω_end - δω_init) 158 | # δω_all[2][δω_all[ii] .< δω_stop] .= 1 .* δω_all[2][δω_all[ii] .< δω_stop] 159 | # δω_all[ii][δω_all[ii] .< δω_stop] .= δω_stop 160 | end 161 | 162 | 163 | 164 | # -- Seting up Simulation -- 165 | # ---------------------------------------------------- 166 | # -- Allocate FFT to go faster -- 167 | ifft_plan = FFTW.plan_ifft(zeros(length(μ), 1)) 168 | fft_plan = FFTW.plan_fft(zeros(length(μ), 1)) 169 | 170 | # -- Define the noise 171 | # ---------------------------------------------------- 172 | function Noise() 173 | Ephoton=ħ.*ω1 174 | phase=2*pi*(rand(length(μ),1)) 175 | array=rand(length(μ),1) 176 | Enoise=array.*sqrt.(Ephoton/2).*exp.(1im*phase).*length(μ) 177 | return FFTW.ifftshift(ifft_plan*(Enoise)) # not that ifftshift matters much here but let's do it right 178 | end 179 | 180 | # -- Pumps input -- 181 | # Need to detune them from the center of the domain (first index) 182 | # Need to do it rhough FFT as it seems in the temporal domain 183 | # introducing a shift through exp(μj x θ) introduce bunch of noise 184 | # --------------------------------------------------------------- 185 | Ain = [1im*zeros(length(μ),1) for ii in collect(1:length(fpmp))] 186 | Ein = [1im*zeros(length(μ),1) for ii in collect(1:length(fpmp))] 187 | for ii in collect(1:length(fpmp)) 188 | Ein[ii][μ0+ind_pmp[ii]] = sqrt(Ppmp[ii])*length(μ) 189 | Ain[ii] = ifft_plan*(FFTW.fftshift(Ein[ii])) .* exp(-1im.*φpmp[ii]) 190 | end 191 | # -- Initial State -- 192 | # --------------------------------------------------------------- 193 | u0 = 1im * zeros(length(μ),1) 194 | u0[:, 1] = DKSinit 195 | 196 | # -- Output Dict -- 197 | # --------------------------------------------------------------- 198 | S = Dict() 199 | # num_probe= 5000 200 | S["u_probe"] = 1im*zeros(num_probe, length(u0)) 201 | S["driving_force"] = 1im*zeros(num_probe,length(u0)) 202 | S["detuning"] = zeros(num_probe,) 203 | S["t_sim"] = zeros(num_probe,) 204 | S["kappa_ext"] = [κext] 205 | S["kappa_0"] = [κ0] 206 | S["alpha"] = [α] 207 | 208 | # -- Misc -- 209 | # --------------------------------------------------------------- 210 | 211 | Dint_shift = FFTW.ifftshift(Dint) 212 | # --------------------------------------------------------------- 213 | # ------------------------------------------ 214 | # -- Define the Functions 215 | # ------------------------------------------ 216 | # --------------------------------------------------------------- 217 | 218 | function ProgressBar_CallBack(it, Nt, S, u0, param) 219 | # -- Update the Progress Bar function every % -- 220 | if it/Nt >= param["probe_pbar"] 221 | param["cnt_pbar"] = param["cnt_pbar"] + 1; 222 | #print(string(Int(round(param["probe_pbar"]*100))) * "\n"); 223 | logfile = open(tmp_dir * "log.log" ,"a") 224 | write(logfile,string(Int(round(param["probe_pbar"]*100))) * "\n") 225 | close(logfile) 226 | probe_pbar2 = param["probe_pbar"] + 0.01; 227 | param["probe_pbar"]=probe_pbar2; 228 | end 229 | return param 230 | end 231 | 232 | function SaveStatus_CallBack(it, Nt, S, u0, param) 233 | # -- Save the data for a data set of 1000 -- 234 | if (it*num_probe/Nt > param["probe"]) 235 | param["probe"] += 1; 236 | S["u_probe"][param["probe"],:]=u0[:,1] #* exp(1im*tsim[Int(it)]*Δω_pmp[Int(it)]/tR); 237 | S["detuning"][param["probe"]] = δω_all[ind_sweep[1]][it]; 238 | S["t_sim"][param["probe"]] = t_sim[it] 239 | S["driving_force"][param["probe"],:] = Fdrive(it) 240 | end 241 | return param 242 | end 243 | 244 | function SaveData(S, num_probe, ω0, dω) 245 | # -- need to compute a full spectral κext for 246 | # extraction of the in-cavity power -- 247 | logfile = open(tmp_dir * "log.log" ,"a") 248 | write(logfile,string(Int(round(100))) * "\n") 249 | close(logfile) 250 | 251 | SaveResultsToFile(tmp_dir, S) 252 | end 253 | 254 | function Fdrive(it) 255 | # -- needed to declare it here as we will use it 256 | # later to save it in the dict - 257 | # ------------------------------------------------ 258 | Force = 0 .* exp.(1im.*θ) 259 | 260 | for ii=1:length(fpmp) 261 | # detuning for each pump 262 | # which is i(δωj + Dint[μ = μj]) - iμjθ with μ0 being the center of the 263 | # domain 264 | # The phase shift iμjθ has already been taken into account previously in 265 | # Ain (due to noise, it needs to be initilized throug FFT) 266 | # --------------------------------------------------------------------- 267 | if ii > 1 268 | σ = (2 .* δω_all[ii][it] .+ Dint[μ0+ind_pmp[ii]] .- 0.5.*δω_all[1][it] ) .* t_sim[it] 269 | else 270 | σ = 0 271 | end 272 | Force .= Force .- 1im .* Ain[ii] .*exp(1im .*σ) 273 | end 274 | return Force #.- 1im*Noise() 275 | end 276 | 277 | 278 | tol = 1e-2 279 | maxiter = 10 280 | success = false 281 | 282 | 283 | L½prop = 1im .*zeros(length(μ),1) 284 | L½prop_cpl = 1im .*zeros(length(μ),1) 285 | A_L½prop = 1im .*zeros(length(μ),1) 286 | NL½prop_0 = 1im .*zeros(length(μ),1) 287 | CPL½prop_0 = 1im .*zeros(length(μ),1) 288 | A½prop = 1im .*zeros(length(μ),1) 289 | Aprop = 1im .*zeros(length(μ),1) 290 | NL½prop_1 = 1im .*zeros(length(μ),1) 291 | NLprop = 1im .*zeros(length(μ),1) 292 | Force = 1im .*zeros(length(μ),1) 293 | retL = 1im .*zeros(length(μ),1) 294 | Eout = 1im .*zeros(length(μ),1) 295 | Aout = 1im .*zeros(length(μ),1) 296 | retNL = 1im .*zeros(length(μ),1) 297 | retcpl = 1im .*zeros(length(μ),1) 298 | 299 | function SSFM½step(A0, it, param) 300 | # ---------------------------------------------------------------------------------------- 301 | # Standard split step fourier method 302 | # ∂A/∂t (t, τ)= [L + NL]A + Fdrive 303 | # 304 | # We can first split the equation in two such that: 305 | # and ∂A_l/∂t = L A_l 306 | # and ∂A_Nl/∂t = NL A_nl 307 | # where L and NL are both operators 308 | # 309 | # In the case of the LLE, the linear equation has an obivous solution in the frequency 310 | # domain (time domain more complicated with the derivatife).: 311 | # ^A^_l(t, ω)= exp(^L^ t) 312 | # 313 | # where the ^^ describe the Fourier Transform of the function 314 | # 315 | # After a smal propagation δt the nonlinear term can be expressed as 316 | # A_nl(t +δt , τ) = exp(NL x δt) A 317 | # 318 | # the linear term has an analytical solution in the frequency domain : 319 | # thus we could easily apply this sollution to our problem such that 320 | # ^A^(t + δt, ω) = exp(^L^ x δt)^A^_nl(t, ω) 321 | # 322 | # From here it is easy to get the valye on A with the driving force, which we will 323 | # increment for each δt 324 | # 325 | # A(t + δt, ω) = FFT-1(^A^(t + δt, ω)) + Fdrive x δt 326 | # 327 | # 328 | # However this direct SSF is not the best stable and implementing a 1/2 SSF is much better 329 | # for more information, please checkout G. Agrawal's book (there is litterally the algorithm 330 | # in it) 331 | 332 | 333 | # ---------------------------------------------------------------------------------------- 334 | # G. Moille - 09/08/2022 - NIST/UMD - gmoille@umd.edu 335 | # ---------------------------------------------------------------------------------------- 336 | # -- Define the Linear, Non-Linear and drive Force --- 337 | # Purpose is for easy modification to ad NL or other terms 338 | function FFT_Lin(it) 339 | return -α/2 .+ 1im .* (Dint_shift .- δω_all[1][it] )*tR 340 | end 341 | 342 | function NL(uu, it) 343 | return -1im*( γ*L* abs.(uu).^2 ) 344 | end 345 | 346 | # --- Linear propagation --- 347 | 348 | A0 = A0 .+ Fdrive(Int(it)) .*sqrt(κext) .* dt; 349 | 350 | L½prop .= exp.(FFT_Lin(Int(it)) .* dt/2); 351 | A_L½prop .= ifft_plan* (fft_plan*(A0) .* L½prop); 352 | NL½prop_0 .= NL(A0, it); 353 | A½prop .= A0; 354 | Aprop .= 1im .* zeros(size(A0)); 355 | 356 | # --- iterative procedur to find ^LN^(t + δt, ω) --- 357 | success = false; 358 | for ii in collect(1:maxiter) 359 | err = 0.0 360 | success = false 361 | NL½prop_1 .= NL(A½prop, it); 362 | NLprop .= (NL½prop_0 .+ NL½prop_1) .* dt/2; 363 | Aprop .= ifft_plan*( fft_plan*(A_L½prop .* exp.(NLprop) ) .* L½prop ) 364 | 365 | # --- check if we concerge or not --- 366 | err = LinearAlgebra.norm(Aprop-A½prop,2)/LinearAlgebra.norm(A½prop,2) 367 | if (err < tol) 368 | success = true 369 | break 370 | else 371 | success = false 372 | A½prop .= Aprop 373 | end 374 | end 375 | 376 | if success 377 | u0 = Aprop 378 | return u0 379 | else 380 | print("Convergence Error") 381 | end 382 | end 383 | 384 | function MainSolver(Nt, S, u0) 385 | # Here we are solvint the most general form of the χ(3)-only-LLE 386 | # For full explenation on how to derive this equation (usually from CMT) 387 | # please refere Taheri, H. et al (2017). "Optical lattice trap for Kerr 388 | # solitons" The European Physical Journal D, 71(6) 389 | # 390 | # ∂A/∂t = (-α/2 - iγL |A|² + i TF⁻¹[Dint])A + 391 | # + Σ2 √κextⱼ Fⱼ exp(i σⱼt+ i Dint(η=ηⱼ) - i(ηⱼ-η₀)θ) 392 | # 393 | # where Dint is computer at η0 (i.e. Dint(η0) = 0) 394 | # σⱼ is the detuning between the pump and the closest mode ηⱼ freqeuncy 395 | # and Fⱼ = -i√(Pinⱼ/ħωⱼ) exp(-φⱼ) 396 | # ---------------------------------------------------------------------------------------- 397 | # G. Moille - 04/23/2020 - NIST/UMD - gmoille@umd.edu 398 | # last modification : 05/05/2020 -- Cinquo de Mayo!! 399 | # ---------------------------------------------------------------------------------------- 400 | param = Dict() 401 | 402 | param["tol"] = 1e-3; 403 | param["maxiter"] = 6; 404 | param["step_factor"] = 0.1; 405 | param["probe_pbar"] = parse(Float64,"0.01"); 406 | param["cnt_pbar"] = 0; 407 | param["probe"] = 0; 408 | 409 | loops = collect(1:1:Nt) 410 | 411 | for it in loops 412 | # -- Solve the Split Step Fourier Step -- 413 | # u0 = SSFM(u0, it, param) 414 | u0 = SSFM½step(u0, it, param) 415 | 416 | # -- Update the Progress bar -- 417 | param = ProgressBar_CallBack(Int(it), Nt, S, u0, param) 418 | # -- Save the Data in the dict -- 419 | param = SaveStatus_CallBack(Int(it), Nt, S, u0, param) 420 | end 421 | SaveData(S, num_probe, ω0, dω) 422 | 423 | end 424 | 425 | # -- Start the solver 426 | # ---------------------------------------------------- 427 | logfile = open(tmp_dir * "log.log" ,"w") 428 | write(logfile,string(Int(round(0))) * "\n") 429 | close(logfile) 430 | MainSolver(Nt, S, u0) 431 | -------------------------------------------------------------------------------- /pyLLE/__init__.py: -------------------------------------------------------------------------------- 1 | from ._llesolver import LLEsolver 2 | from ._analyzedisp import AnalyzeDisp -------------------------------------------------------------------------------- /pyLLE/_analyzedisp.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.interpolate as itp 3 | import scipy.io as io 4 | from scipy import constants as cts 5 | import matplotlib as mpl 6 | import matplotlib.pyplot as plt 7 | from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot 8 | import plotly.graph_objs as go 9 | import ipdb 10 | # backend = mpl.get_backend() 11 | # print(backend) 12 | 13 | class AnalyzeDisp(object): 14 | ''' 15 | Calls to analyze the dispersion of a simulated resonator 16 | Initialization input. Everything is in SI ([]=facultative): 17 | **kwargs 18 | - f_center : pump frequency 19 | - file : .txt file to load 20 | - R : radius of the resonator 21 | - rM_fit .: lower and upper bonds of mode to fit the dispersion 22 | - rM_sim .: lower and upper bonds of the modes to extrapolate for the simulation 23 | - f : matplotlib figure handle 24 | - ax : matplotlib axes handle 25 | - label : list of the string for each plot to be labelled 26 | - plottype : define the type of plot 'all' [defaults], 'sim', 'fit', 'fem', 'ind' 27 | 28 | ''' 29 | 30 | def __init__(self, **kwargs): 31 | cts.c = 299792458 32 | self.dispfile = kwargs.get('file', None) 33 | self.R = kwargs.get('R', 23e-6) 34 | self.f_center = kwargs.get('f_center', None) 35 | self.fpmp = kwargs.get('fpmp', None) 36 | self.D1_manual = kwargs.get('D1_manual', None) 37 | self.rM_fit = kwargs.get('rM_fit', []) 38 | self.rM_sim = kwargs.get('rM_sim', []) 39 | self.debug = kwargs.get('debug', False) 40 | self.plottype = kwargs.get('plottype', 'all') 41 | self._logger = kwargs.get('logger', None) 42 | self.pyType = kwargs.get('pyType', 'normal') 43 | self.fig = kwargs.get('fig', 'normal') 44 | assert type(self.dispfile) is str, 'Please provide a file' 45 | assert len(self.rM_fit) > 1, 'Please the modes to fit' 46 | 47 | def GetDint(self): 48 | ''' 49 | Retrieve the dispersion of a resonator based on the frequency of 50 | resonance and azimuthal mode order. The data are fit using a cubic spline method 51 | 52 | **Output** 53 | - self.PrM_fit: scipy.interpolate object which fitted the data 54 | - self.Dint_fit: fitted integrated dispersion for the simulated mode 55 | - self.neff_pmp: effective index at the pump frequency 56 | - self.ng_pmp: group index at the pump frequency 57 | ''' 58 | 59 | 60 | def getFreqModes(f_center= None): 61 | FSR0 = 1e12*23e-6/self.R 62 | lines = open(self.dispfile,'r').readlines() 63 | self.rM = np.array([float(ll.strip().split(',')[0]) for ll in lines]) 64 | self.rf = np.array([float(ll.strip().split(',')[1]) for ll in lines]) 65 | # -- Find the pumped mode -- 66 | if not f_center: 67 | pmp_ind = np.where(np.abs(self.rf-self.fpmp[0]) < 0.5*FSR0)[0] 68 | assert pmp_ind.size == 1, 'Wavelength not found!' 69 | self.pmp_ind_fit = pmp_ind[0] 70 | else: 71 | pmp_ind = np.where(np.abs(self.rf-f_center) < 0.5*FSR0)[0] 72 | assert pmp_ind.size == 1, 'Wavelength not found!' 73 | return pmp_ind[0] 74 | return self.pmp_ind_fit 75 | 76 | def getGroupIndex(): 77 | # -- Compute the effective/group index -- 78 | L = 2*np.pi*self.R 79 | df = np.gradient(self.rf) 80 | self.neff = self.rM * cts.c/(self.rf*2*np.pi*self.R) 81 | self.neff_pmp = self.neff[self.pmp_ind_fit] 82 | self.ng = cts.c/(df*L) 83 | self.ng_pmp = self.ng[self.pmp_ind_fit] 84 | self.tR = L*self.ng_pmp/cts.c 85 | 86 | def getDispersion(): 87 | # Compute the dispersion 88 | df = np.gradient(self.rf) 89 | d1_vg = np.gradient(self.ng)/cts.c 90 | D = -(self.rf**2/cts.c) * d1_vg/df 91 | self.D = D 92 | 93 | def getIntegratedDisp(ind_pmp): 94 | # -- Compute Dint -- 95 | dm = np.array([-2, -1, 0, 1, 2]) 96 | drf = self.rf - self.rf[self.pmp_ind_fit] 97 | Dfit = np.polyfit(dm, drf[ind_pmp+dm], 2) 98 | self.FSR = Dfit[1] 99 | self.D2 = Dfit[0]*2*np.pi 100 | if not self.D1_manual: 101 | D1 = self.FSR * 2*np.pi 102 | else: 103 | D1 = self.D1_manual 104 | μ = self.rM - self.rM[ind_pmp] 105 | ω = 2*np.pi*self.rf 106 | Dint = ω - (ω[ind_pmp] + D1 * μ) 107 | β2 = -self.ng_pmp/cts.c*(2*Dfit[0])/Dfit[1]**2/2/np.pi 108 | self.μ0 = μ 109 | return μ, Dint, D1 110 | 111 | def fitDintDomain(ind0,ind_master, Dint): 112 | 113 | if self.rM_fit == [None, None]: 114 | μfit = [self.μ0[0], self.μ0[-1]] 115 | shift = 0 116 | else: 117 | μfit = self.rM_fit 118 | shift = ind0 - ind_master 119 | # print(shift) 120 | μfit = [rm-shift for rm in μfit] 121 | # print(μfit) 122 | M = np.arange(ind0+μfit[0], 123 | ind0+μfit[1]+1, 124 | dtype=int) 125 | # print(M) 126 | μselect = np.arange(μfit[0],μfit[1]+1, dtype=int) 127 | assert M[0] >= 0, 'Left range for mode order not correct' 128 | assert M[-1] <= self.rM.size, 'Right range for mode order not correct' 129 | 130 | 131 | # self.PrM_fit = itp.splrep(μfit, Dint2fit) 132 | M2fit = self.rM[M] - self.rM[ind0] 133 | Dint2fit = Dint[M] 134 | fitfun = itp.splrep(M2fit, Dint2fit) 135 | fit_selected = itp.splev(μselect, fitfun) 136 | pmp_ind = np.argwhere(M2fit == 0).flatten()[0] 137 | return fitfun, μselect, fit_selected, pmp_ind 138 | 139 | def doFitSimulationDint(fitfun, ind0, ind_master): 140 | # if self.rM_fit == [None, None]: 141 | # shift = 0 142 | # else: 143 | # μfit = self.rM_fit 144 | shift = ind0 - ind_master 145 | 146 | μ2fit = [rm-shift for rm in self.rM_sim] 147 | ind_sim = np.arange(μ2fit[0], μ2fit[1]+1, dtype=int) 148 | 149 | Dint_fit = itp.splev(ind_sim, fitfun) 150 | 151 | pmp_ind = np.argwhere(ind_sim == 0).flatten()[0] 152 | 153 | return μ2fit, Dint_fit, pmp_ind 154 | 155 | 156 | 157 | # -- Get all parameters that are not relative to the pump mode -- 158 | # ---------------------------------------------------------------------------- 159 | 160 | 161 | self.μsim = [] 162 | self.Dint_fit = [] 163 | self.Dint_sim = [] 164 | self.pmp_ind = [] 165 | self.Dint = [] 166 | self.D1 = [] 167 | self.μsim = [] 168 | self.μfit = [] 169 | self.ind_pmp_sim = [] 170 | self.ind_pmp_fit = [] 171 | # -- Get all parameters that are relative to the pump mode -- 172 | # ---------------------------------------------------------------------------- 173 | # The data collected here are only entended for visulation purpose as the 174 | # integration Dint that is use in pyLLE is computed at the center of the 175 | # domain. For more information, please look at ComputeLLE.jl file (core 176 | # function in Julia of pyLLE) or chekc out Taheri et al. eq 12 177 | cnt_f = 0 178 | for ff in self.fpmp: 179 | if not ff == self.fpmp[0]: 180 | ind_pmp = getFreqModes(f_center= ff) 181 | else: 182 | ind_pmp = getFreqModes() 183 | ind_master = ind_pmp 184 | getGroupIndex() 185 | getDispersion() 186 | 187 | # will do the fit relative to the first pump 188 | μ_, Dint_, D1_ = getIntegratedDisp(ind_pmp) 189 | ff, μfit_, Dint_fit_, pmp_fit_ = fitDintDomain(ind_pmp,ind_master, Dint_) 190 | μsim_, Dint_sim_, pmp_sim_ = doFitSimulationDint(ff, ind_pmp, ind_master) 191 | 192 | self.Dint += [Dint_] 193 | self.Dint_fit += [Dint_fit_] 194 | self.Dint_sim += [Dint_sim_] 195 | self.D1 += [D1_] 196 | self.ind_pmp_sim += [pmp_sim_] 197 | self.ind_pmp_fit += [pmp_fit_] 198 | self.μsim += [μsim_] 199 | self.μfit += [μfit_] 200 | self.fpmp[cnt_f] = self.rf[ind_pmp] 201 | 202 | cnt_f += 1 203 | 204 | ff0 = self.fpmp[0] 205 | # print(μdomain) 206 | ind0 = np.sum(self.μsim[0])/2 207 | # ind1 = np.sum(self.μsim[1])/2 208 | assert ind0 == int(ind0), 'Domain not correct' 209 | ind_center = int(self.pmp_ind_fit + ind0) 210 | 211 | 212 | for ii in range(len(self.fpmp)): 213 | self.pmp_ind += [int(-1*np.sum(self.μsim[ii])/2)] 214 | 215 | 216 | f_center = self.rf[ind_center] 217 | ind_center = getFreqModes(f_center= f_center) 218 | μ_, Dint_, D1_ = getIntegratedDisp(ind_center) 219 | ff, μfit_, Dint_fit_, pmp_fit_ = fitDintDomain(ind_center,ind_center, Dint_) 220 | μsim_, Dint_sim_, pmp_sim_ = doFitSimulationDint(ff, ind_center, ind_center-ind0) 221 | 222 | self.fpmp += [f_center] 223 | self.Dint += [Dint_] 224 | self.Dint_fit += [Dint_fit_] 225 | self.Dint_sim += [Dint_sim_] 226 | self.D1 += [D1_] 227 | self.ind_pmp_sim += [pmp_sim_] 228 | self.ind_pmp_fit += [pmp_fit_] 229 | self.μsim += [μsim_] 230 | self.μfit += [μfit_] 231 | 232 | # μfit = self.μfit[ii] #+ self.ind_pmp_fit[ii] 233 | μsim = self.μsim[ii] #+ self.ind_pmp_sim[ii] 234 | self.freq_fit = self.fpmp[0] + np.arange(μsim[0], μsim[-1]+1)*self.D1[0]/(2*np.pi) 235 | 236 | # dφ = -(drf-(rM-rM[self.pmp_ind_fit])*FSR_p)/FSR_p*2*np.pi 237 | 238 | def DisplayParam(self): 239 | 240 | Info = '-- Dispersion Analysis --\n' 241 | Info += '\tPump index: {}\n'.format(self.pmp_ind_fit) 242 | Info += '\tCenter Pump: {:.3f} THz\n'.format(self.rf[self.pmp_ind_fit]*1e-12) 243 | Info += '\tFSR: {:.2f} GHz\n'.format(self.FSR*1e-9) 244 | Info += '\tD2: {:.2f} MHz\n'.format(self.D2*1e-6) 245 | print(Info) 246 | 247 | if self._logger: 248 | Info += '\t mu_fit: [{:.0f}, {:.0f}]\n'.format(self.rM_fit[0], 249 | self.rM_fit[1]) 250 | Info += '\t mu_sim: [{:.0f}, {:.0f}]\n'.format(self.rM_sim[0], 251 | self.rM_sim[1]) 252 | 253 | self._logger.info('AnalyzeDisp', Info) 254 | 255 | def DisplayPlot(self, display_center= False): 256 | 257 | def PlotJupyter(): 258 | init_notebook_mode(connected=True) 259 | trace = [] 260 | for ii in range(len(self.fpmp)-1): 261 | μfit = self.μfit[ii] #+ self.ind_pmp_fit[ii] 262 | μsim = self.μsim[ii] #+ self.ind_pmp_sim[ii] 263 | dν_fit = np.arange(μfit[0], μfit[-1]+1)*self.D1[0]/(2*np.pi) 264 | dν_sim = np.arange(μsim[0], μsim[-1]+1)*self.D1[0]/(2*np.pi) 265 | ν0 = self.fpmp[ii] 266 | rf = self.rf 267 | rf_fit = (ν0+dν_fit) 268 | rf_sim = (ν0+dν_sim) 269 | 270 | trace += [go.Scatter( 271 | x = rf*1e-12, 272 | y = (self.Dint[0] - self.Dint[0][self.ind_pmp_fit[ii]] )*1e-9/(2*np.pi), 273 | legendgroup = 'Pump #{:.0f}'.format(ii), 274 | mode = 'markers', 275 | name = 'FEM Simulation')] 276 | if self.plottype.lower() == 'all': 277 | 278 | trace += [go.Scatter( 279 | x = rf_fit*1e-12, 280 | y = (self.Dint_fit[0]- self.Dint[0][self.ind_pmp_fit[ii]])*1e-9/(2*np.pi), 281 | line = dict(width = 2, dash = 'dash'), 282 | legendgroup = 'Pump #{:.0f}'.format(ii), 283 | name = 'Fit')] 284 | trace += [go.Scatter( 285 | x = rf_sim*1e-12, 286 | y = (self.Dint_sim[0] - self.Dint[0][self.ind_pmp_fit[ii]])*1e-9/(2*np.pi), 287 | legendgroup = 'Pump #{:.0f}'.format(ii), 288 | mode = 'lines', 289 | name = 'LLE simulation')] 290 | 291 | 292 | if self.plottype.lower() == 'sim': 293 | 294 | trace += [go.Scatter( 295 | x = rf_sim*1e-12, 296 | y = self.Dint_sim[ii]*1e-9/(2*np.pi), 297 | legendgroup = 'Pump #{:.0f}'.format(ii), 298 | mode = 'lines', 299 | name = 'LLE simulation')] 300 | 301 | if self.plottype.lower() == 'fit': 302 | 303 | trace += [go.Scatter( 304 | x = rf_fit*1e-12, 305 | y = self.Dint_fit[ii]*1e-9/(2*np.pi), 306 | line = dict(width = 2, dash = 'dash'), 307 | legendgroup = 'Pump #{:.0f}'.format(ii), 308 | name = 'Fit')] 309 | if self.plottype.lower() == 'fem': 310 | pass 311 | 312 | self.fig = go.FigureWidget(data=trace) 313 | 314 | self.fig.add_hline(y=0, line_width=3,line_color="white", opacity = 1) 315 | 316 | self.fig.update_layout(xaxis = dict(title = 'Frequency (THz)'), 317 | yaxis = dict(title = 'Dint (GHz)')) 318 | 319 | def PlotMatplotlib(): 320 | self.fig, ax = plt.subplots() 321 | for ii in range(len(self.fpmp)-1): 322 | μfit = self.μfit[ii] #+ self.ind_pmp_fit[ii] 323 | μsim = self.μsim[ii] #+ self.ind_pmp_sim[ii] 324 | dν_fit = np.arange(μfit[0], μfit[-1]+1)*self.D1[0]/(2*np.pi) 325 | dν_sim = np.arange(μsim[0], μsim[-1]+1)*self.D1[0]/(2*np.pi) 326 | ν0 = self.fpmp[ii] 327 | rf = self.rf 328 | rf_fit = (ν0+dν_fit) 329 | rf_sim = (ν0+dν_sim) 330 | 331 | ax.plot(rf*1e-12, 332 | self.Dint[ii]*1e-9/(2*np.pi), 333 | 'o',ms= 3, 334 | label = 'FEM Simulation') 335 | 336 | if self.plottype.lower() == 'all': 337 | 338 | ax.plot(rf_fit*1e-12, 339 | self.Dint_fit[ii]*1e-9/(2*np.pi), 340 | '--', 341 | label = 'Fit') 342 | ax.plot(rf_sim*1e-12, 343 | self.Dint_sim[ii]*1e-9/(2*np.pi), 344 | label = 'LLE simulation') 345 | 346 | if self.plottype.lower() == 'sim': 347 | ax.plot(rf_sim*1e-12, 348 | self.Dint_sim[ii]*1e-9/(2*np.pi), 349 | label = 'LLE simulation') 350 | 351 | if self.plottype.lower() == 'fit': 352 | ax.plot(rf_fit*1e-12, 353 | self.Dint_fit[ii]*1e-9/(2*np.pi), 354 | label = 'Fit') 355 | 356 | if not self.pyType == 'jupyter': 357 | PlotMatplotlib() 358 | else: 359 | PlotJupyter() 360 | 361 | return self.fig 362 | # if __name__ == '__main__': 363 | # plt.close('all') 364 | # analyze = AnalyzeDisp(file='TestDispersion.mat', 365 | # lbd_center = 1500e-9, 366 | # rM_fit=[-50, 160], 367 | # debug=True) 368 | # analyze.GetBeta() 369 | -------------------------------------------------------------------------------- /pypiStuff/build/lib/pyLLE/ComputeLLE.jl: -------------------------------------------------------------------------------- 1 | using HDF5 2 | using Base 3 | using FFTW 4 | using LinearAlgebra 5 | 6 | function Loadh5Param(dir) 7 | h5file = dir * "ParamLLEJulia.h5" 8 | res = Dict() 9 | sim = Dict() 10 | sim_name = ["res", "sim"] 11 | par = [["Qc", "R", "ng", "Qi", "gamma","dispfile"], ["Pin", "Tscan", "domega_init", "domega_end", "domega", "f_pmp", "mu_sim_center", "ind_pmp", "Dint", "ind_pump_sweep","f_center", "phi_pmp", "D1", "DKSinit_imag","DKSinit_real" ]] 12 | cnt = 1 13 | for sim_par = [res, sim] 14 | for it = par[cnt] 15 | sim_par[it] = h5read(h5file, sim_name[cnt] *"/" * it) 16 | end 17 | cnt += 1 18 | end 19 | 20 | return res, sim 21 | end 22 | 23 | 24 | function SaveResultsToFile(dir, S) 25 | h5file = dir * "ResultsJulia.h5" 26 | print(h5file) 27 | print("\n") 28 | h5open(h5file, "w") do file 29 | g = create_group(file, "Results") # create a group 30 | for ii in S 31 | print(ii[1]) 32 | print("\n") 33 | g[ii[1]*"Real"] = real(ii[2]) # create a scalar dataset inside the group 34 | g[ii[1]*"Imag"] = imag(ii[2]) 35 | end 36 | # attrs(g)["Description"] = "This group contains only a single dataset" 37 | end 38 | end 39 | 40 | # ---------------------------------------------------- 41 | # -- STARTING MAIN SCRIPT -- 42 | # ---------------------------------------------------- 43 | tmp_dir = ARGS[1] #"/var/folders/_v/2zfybdtj589c1fwk78q_q5qr0000gn/T/tmpqmatmei5" # 44 | tol = parse(Float64,ARGS[2]) #1e-3 # 45 | maxiter = parse(Int,ARGS[3]) #10 # 46 | stepFactor = parse(Float64,ARGS[4]) #1# 47 | 48 | # tmp_dir = "/tmp/tmpbyi6lbwx" 49 | res, sim = Loadh5Param(tmp_dir) 50 | logfile = open(tmp_dir * "Log.log" ,"w") 51 | 52 | # ---------------------------------------------------- 53 | # -- Collect Data --- 54 | # ---------------------------------------------------- 55 | c0 = 299792458 56 | ħ = 6.634e-34/2/pi 57 | 58 | # -- res parameters -- 59 | ng = res["ng"][1] 60 | R = res["R"][1] 61 | γ = res["gamma"][1] 62 | L = 2*pi*R 63 | 64 | Q0 = res["Qi"][1] 65 | Qc = res["Qc"][1] 66 | fpmp = sim["f_pmp"] 67 | Ppmp = sim["Pin"] 68 | φpmp = sim["phi_pmp"] 69 | fcenter= sim["f_center"][1] 70 | 71 | DKSinit_real = sim["DKSinit_real"] 72 | DKSinit_imag = sim["DKSinit_imag"] 73 | 74 | DKSinit = DKSinit_real .+ 1im .* DKSinit_imag 75 | 76 | D1= sim["D1"][1] 77 | FSR = D1/2π 78 | ω0 = 2π*fpmp 79 | ωcenter = 2π*fcenter 80 | 81 | # -- Setup the different Parameters -- 82 | # ---------------------------------------------------- 83 | tR = 1/FSR 84 | T = 1*tR 85 | κext = ω0[1]/Qc*tR 86 | κ0 = ω0[1]/Q0*tR 87 | α = κ0 + κext 88 | # -- Retrieve sim parameters -- 89 | # ---------------------------------------------------- 90 | # debug = Bool(sim["debug"][1]) 91 | δω_init = sim["domega_init"][1] 92 | δω_end = sim["domega_end"][1] 93 | ind_sweep = sim["ind_pump_sweep"] .+ 1 #because of 0 and 1 index start difference between Julia nd pyhton 94 | t_end = sim["Tscan"][1] 95 | Dint = sim["Dint"] 96 | 97 | 98 | δω = sim["domega"] 99 | ind_pmp = [ii+1 for ii in sim["ind_pmp"]] #because of 0 and 1 index start difference between Julia 100 | μ_sim = sim["mu_sim_center"] 101 | μ = collect(μ_sim[1]:μ_sim[2]) 102 | μ0 = Int(1 + (length(μ)-1)/2) # center of the domain 103 | 104 | # -- Losses -- 105 | # ---------------------------------------------------- 106 | dω = collect(μ_sim[1]:μ_sim[end])*2*pi*FSR 107 | dω_pmp1 = collect(μ_sim[1]-ind_pmp[1]-1:μ_sim[end]-ind_pmp[1]-1)*2*pi*FSR 108 | ω1 = ω0[1] .+ dω_pmp1 109 | 110 | # Make sure there is no residue in the center of the domain 111 | Dint= (Dint .- Dint[μ0]) 112 | # dφ_Kerr=κext*Pin*γ*L/α^2 113 | 114 | Ptot = 0 115 | for ii=1:length(fpmp) 116 | global Ptot += Ppmp[ii] 117 | end 118 | # dt=0.2/(sqrt(Ptot)) 119 | dt = 1 120 | t_end = t_end*tR 121 | t_ramp = t_end 122 | 123 | # -- Sim length -- 124 | # ---------------------------------------------------- 125 | Nt = round(t_ramp/tR/dt) 126 | t1 = 0 127 | 128 | # -- Angle through the resonator -- 129 | # ---------------------------------------------------- 130 | θ = Array(range(0,stop=2π,length=length(μ))) 131 | # -- Time scale --- 132 | # Here the normaizatiton of time is such that 133 | # t=0 when the pump is align with the cold cavity 134 | # δω=0 → t=0- 135 | # hence we need to rescale if the detuning is not symmetric 136 | # ---------------------------------------------------- 137 | δωtot = (abs(δω_end) + abs(δω_init)) 138 | δωcent_perc = -1*sign(δω_end+δω_init)*(abs(δω_end + δω_init)/2)/δωtot 139 | t_sim = Array(range(-t_ramp/2 + δωcent_perc*t_ramp, 140 | stop = t_ramp/2 + δωcent_perc*t_ramp, 141 | length=Int(Nt))) 142 | 143 | # -- Frequency sweep --- 144 | # index = 1 will always be the main pump, i.e. from where the Dint is defined 145 | # δω_init = δω_init * tR 146 | # δω_end = δω_end * tR 147 | # ---------------------------------------------------- 148 | xx = collect(1:Nt) 149 | 150 | δω_all = [δω[ii]*ones(Int(Nt),1) for ii in collect(1:length(fpmp))] 151 | # define which thing we are actually sweeping 152 | for ii in ind_sweep 153 | δω_all[ii][:] = δω_init.+ xx/Nt * (δω_end - δω_init) 154 | end 155 | 156 | # -- Seting up Simulation -- 157 | # ---------------------------------------------------- 158 | # -- Allocate FFT to go faster -- 159 | ifft_plan = FFTW.plan_ifft(zeros(length(μ), 1)) 160 | fft_plan = FFTW.plan_fft(zeros(length(μ), 1)) 161 | 162 | # -- Define the noise 163 | # ---------------------------------------------------- 164 | function Noise() 165 | Ephoton=ħ.*ω1 166 | phase=2*pi*(rand(length(μ),1)) 167 | array=rand(length(μ),1) 168 | Enoise=array.*sqrt.(Ephoton/2).*exp.(1im*phase).*length(μ) 169 | return FFTW.ifftshift(ifft_plan*(Enoise)) # not that ifftshift matters much here but let's do it right 170 | end 171 | 172 | # -- Pumps input -- 173 | # Need to detune them from the center of the domain (first index) 174 | # Need to do it rhough FFT as it seems in the temporal domain 175 | # introducing a shift through exp(μj x θ) introduce bunch of noise 176 | # --------------------------------------------------------------- 177 | Ain = [1im*zeros(length(μ),1) for ii in collect(1:length(fpmp))] 178 | Ein = [1im*zeros(length(μ),1) for ii in collect(1:length(fpmp))] 179 | for ii in collect(1:length(fpmp)) 180 | Ein[ii][μ0+ind_pmp[ii]] = sqrt(Ppmp[ii])*length(μ) 181 | Ain[ii] = ifft_plan*(FFTW.fftshift(Ein[ii])) .* exp(-1im.*φpmp[ii]) 182 | end 183 | # -- Initial State -- 184 | # --------------------------------------------------------------- 185 | u0 = 1im * zeros(length(μ),1) 186 | u0[:, 1] = DKSinit 187 | 188 | # -- Output Dict -- 189 | # --------------------------------------------------------------- 190 | S = Dict() 191 | num_probe=5000 192 | S["u_probe"] = 1im*zeros(num_probe, length(u0)) 193 | S["driving_force"] = 1im*zeros(num_probe,length(u0)) 194 | S["detuning"] = zeros(num_probe,) 195 | S["t_sim"] = zeros(num_probe,) 196 | S["kappa_ext"] = [κext] 197 | S["kappa_0"] = [κ0] 198 | S["alpha"] = [α] 199 | 200 | # -- Misc -- 201 | # --------------------------------------------------------------- 202 | 203 | Dint_shift = FFTW.ifftshift(Dint) 204 | # --------------------------------------------------------------- 205 | # ------------------------------------------ 206 | # -- Define the Functions 207 | # ------------------------------------------ 208 | # --------------------------------------------------------------- 209 | 210 | function ProgressBar_CallBack(it, Nt, S, u0, param) 211 | # -- Update the Progress Bar function every % -- 212 | if it/Nt >= param["probe_pbar"] 213 | param["cnt_pbar"] = param["cnt_pbar"] + 1; 214 | #print(string(Int(round(param["probe_pbar"]*100))) * "\n"); 215 | logfile = open(tmp_dir * "log.log" ,"a") 216 | write(logfile,string(Int(round(param["probe_pbar"]*100))) * "\n") 217 | close(logfile) 218 | probe_pbar2 = param["probe_pbar"] + 0.01; 219 | param["probe_pbar"]=probe_pbar2; 220 | end 221 | return param 222 | end 223 | 224 | function SaveStatus_CallBack(it, Nt, S, u0, param) 225 | # -- Save the data for a data set of 1000 -- 226 | if (it*num_probe/Nt > param["probe"]) 227 | param["probe"] += 1; 228 | S["u_probe"][param["probe"],:]=u0[:,1] #* exp(1im*tsim[Int(it)]*Δω_pmp[Int(it)]/tR); 229 | S["detuning"][param["probe"]] = δω_all[ind_sweep[1]][it]; 230 | S["t_sim"][param["probe"]] = t_sim[it] 231 | S["driving_force"][param["probe"],:] = Fdrive(it) 232 | end 233 | return param 234 | end 235 | 236 | function SaveData(S, num_probe, ω0, dω) 237 | # -- need to compute a full spectral κext for 238 | # extraction of the in-cavity power -- 239 | logfile = open(tmp_dir * "log.log" ,"a") 240 | write(logfile,string(Int(round(100))) * "\n") 241 | close(logfile) 242 | 243 | SaveResultsToFile(tmp_dir, S) 244 | end 245 | 246 | function Fdrive(it) 247 | # -- needed to declare it here as we will use it 248 | # later to save it in the dict - 249 | # ------------------------------------------------ 250 | Force = 0 .* exp.(1im.*θ) 251 | 252 | for ii=1:length(fpmp) 253 | # detuning for each pump 254 | # which is i(δωj + Dint[μ = μj]) - iμjθ with μ0 being the center of the 255 | # domain 256 | # The phase shift iμjθ has already been taken into account previously in 257 | # Ain (due to noise, it needs to be initilized throug FFT) 258 | # --------------------------------------------------------------------- 259 | if ii > 1 260 | σ = (δω_all[ii][it] .+ Dint[μ0+ind_pmp[ii]-1] .- 2 .* δω_all[ind_sweep[1]][it] ) .* t_sim[it] 261 | else 262 | σ = 0 263 | end 264 | # σ = (δω_all[ii][it] .+ Dint[μ0+ind_pmp[ii]-1]) .* t_sim[it] 265 | Force .= Force .- 1im .* Ain[ii] .*exp(1im .*σ) 266 | end 267 | return Force #.- 1im*Noise() 268 | end 269 | 270 | 271 | tol = 1e-2 272 | maxiter = 10 273 | success = false 274 | 275 | 276 | L½prop = 1im .*zeros(length(μ),1) 277 | L½prop_cpl = 1im .*zeros(length(μ),1) 278 | A_L½prop = 1im .*zeros(length(μ),1) 279 | NL½prop_0 = 1im .*zeros(length(μ),1) 280 | CPL½prop_0 = 1im .*zeros(length(μ),1) 281 | A½prop = 1im .*zeros(length(μ),1) 282 | Aprop = 1im .*zeros(length(μ),1) 283 | NL½prop_1 = 1im .*zeros(length(μ),1) 284 | NLprop = 1im .*zeros(length(μ),1) 285 | Force = 1im .*zeros(length(μ),1) 286 | retL = 1im .*zeros(length(μ),1) 287 | Eout = 1im .*zeros(length(μ),1) 288 | Aout = 1im .*zeros(length(μ),1) 289 | retNL = 1im .*zeros(length(μ),1) 290 | retcpl = 1im .*zeros(length(μ),1) 291 | 292 | function SSFM½step(A0, it, param) 293 | # ---------------------------------------------------------------------------------------- 294 | # Standard split step fourier method 295 | # ∂A/∂t (t, τ)= [L + NL]A + Fdrive 296 | # 297 | # We can first split the equation in two such that: 298 | # and ∂A_l/∂t = L A_l 299 | # and ∂A_Nl/∂t = NL A_nl 300 | # where L and NL are both operators 301 | # 302 | # In the case of the LLE, the linear equation has an obivous solution in the frequency 303 | # domain (time domain more complicated with the derivatife).: 304 | # ^A^_l(t, ω)= exp(^L^ t) 305 | # 306 | # where the ^^ describe the Fourier Transform of the function 307 | # 308 | # After a smal propagation δt the nonlinear term can be expressed as 309 | # A_nl(t +δt , τ) = exp(NL x δt) A 310 | # 311 | # the linear term has an analytical solution in the frequency domain : 312 | # thus we could easily apply this sollution to our problem such that 313 | # ^A^(t + δt, ω) = exp(^L^ x δt)^A^_nl(t, ω) 314 | # 315 | # From here it is easy to get the valye on A with the driving force, which we will 316 | # increment for each δt 317 | # 318 | # A(t + δt, ω) = FFT-1(^A^(t + δt, ω)) + Fdrive x δt 319 | # 320 | # 321 | # However this direct SSF is not the best stable and implementing a 1/2 SSF is much better 322 | # for more information, please checkout G. Agrawal's book (there is litterally the algorithm 323 | # in it) 324 | 325 | 326 | # ---------------------------------------------------------------------------------------- 327 | # G. Moille - 09/08/2022 - NIST/UMD - gmoille@umd.edu 328 | # ---------------------------------------------------------------------------------------- 329 | # -- Define the Linear, Non-Linear and drive Force --- 330 | # Purpose is for easy modification to ad NL or other terms 331 | function FFT_Lin(it) 332 | return -α/2 .+ 1im .* (Dint_shift .- δω_all[ind_sweep[1]][it] .* 2 )*tR 333 | end 334 | 335 | function NL(uu, it) 336 | return -1im*( γ*L* abs.(uu).^2 ) 337 | end 338 | 339 | # --- Linear propagation --- 340 | 341 | A0 = A0 .+ Fdrive(Int(it)) .*sqrt(κext) .* dt; 342 | 343 | L½prop .= exp.(FFT_Lin(Int(it)) .* dt/2); 344 | A_L½prop .= ifft_plan* (fft_plan*(A0) .* L½prop); 345 | NL½prop_0 .= NL(A0, it); 346 | A½prop .= A0; 347 | Aprop .= 1im .* zeros(size(A0)); 348 | 349 | # --- iterative procedur to find ^LN^(t + δt, ω) --- 350 | success = false; 351 | for ii in collect(1:maxiter) 352 | err = 0.0 353 | success = false 354 | NL½prop_1 .= NL(A½prop, it); 355 | NLprop .= (NL½prop_0 .+ NL½prop_1) .* dt/2; 356 | Aprop .= ifft_plan*( fft_plan*(A_L½prop .* exp.(NLprop) ) .* L½prop ) 357 | 358 | # --- check if we concerge or not --- 359 | err = LinearAlgebra.norm(Aprop-A½prop,2)/LinearAlgebra.norm(A½prop,2) 360 | if (err < tol) 361 | success = true 362 | break 363 | else 364 | success = false 365 | A½prop .= Aprop 366 | end 367 | end 368 | 369 | if success 370 | u0 = Aprop 371 | return u0 372 | else 373 | print("Convergence Error") 374 | end 375 | end 376 | 377 | function MainSolver(Nt, S, u0) 378 | # Here we are solvint the most general form of the χ(3)-only-LLE 379 | # For full explenation on how to derive this equation (usually from CMT) 380 | # please refere Taheri, H. et al (2017). "Optical lattice trap for Kerr 381 | # solitons" The European Physical Journal D, 71(6) 382 | # 383 | # ∂A/∂t = (-α/2 - iγL |A|² + i TF⁻¹[Dint])A + 384 | # + Σ2 √κextⱼ Fⱼ exp(i σⱼt+ i Dint(η=ηⱼ) - i(ηⱼ-η₀)θ) 385 | # 386 | # where Dint is computer at η0 (i.e. Dint(η0) = 0) 387 | # σⱼ is the detuning between the pump and the closest mode ηⱼ freqeuncy 388 | # and Fⱼ = -i√(Pinⱼ/ħωⱼ) exp(-φⱼ) 389 | # ---------------------------------------------------------------------------------------- 390 | # G. Moille - 04/23/2020 - NIST/UMD - gmoille@umd.edu 391 | # last modification : 05/05/2020 -- Cinquo de Mayo!! 392 | # ---------------------------------------------------------------------------------------- 393 | param = Dict() 394 | 395 | param["tol"] = 1e-3; 396 | param["maxiter"] = 6; 397 | param["step_factor"] = 0.1; 398 | param["probe_pbar"] = parse(Float64,"0.01"); 399 | param["cnt_pbar"] = 0; 400 | param["probe"] = 0; 401 | 402 | loops = collect(1:1:Nt) 403 | 404 | for it in loops 405 | # -- Solve the Split Step Fourier Step -- 406 | # u0 = SSFM(u0, it, param) 407 | u0 = SSFM½step(u0, it, param) 408 | 409 | # -- Update the Progress bar -- 410 | param = ProgressBar_CallBack(Int(it), Nt, S, u0, param) 411 | # -- Save the Data in the dict -- 412 | param = SaveStatus_CallBack(Int(it), Nt, S, u0, param) 413 | end 414 | SaveData(S, num_probe, ω0, dω) 415 | 416 | end 417 | 418 | # -- Start the solver 419 | # ---------------------------------------------------- 420 | logfile = open(tmp_dir * "log.log" ,"w") 421 | write(logfile,string(Int(round(0))) * "\n") 422 | close(logfile) 423 | MainSolver(Nt, S, u0) 424 | -------------------------------------------------------------------------------- /pypiStuff/build/lib/pyLLE/__init__.py: -------------------------------------------------------------------------------- 1 | from ._llesolver import LLEsolver 2 | from ._analyzedisp import AnalyzeDisp -------------------------------------------------------------------------------- /pypiStuff/build/lib/pyLLE/_analyzedisp.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.interpolate as itp 3 | import scipy.io as io 4 | from scipy import constants as cts 5 | import matplotlib as mpl 6 | import matplotlib.pyplot as plt 7 | from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot 8 | import plotly.graph_objs as go 9 | import ipdb 10 | # backend = mpl.get_backend() 11 | # print(backend) 12 | 13 | class AnalyzeDisp(object): 14 | ''' 15 | Calls to analyze the dispersion of a simulated resonator 16 | Initialization input. Everything is in SI ([]=facultative): 17 | **kwargs 18 | - f_center : pump frequency 19 | - file : .txt file to load 20 | - R : radius of the resonator 21 | - rM_fit .: lower and upper bonds of mode to fit the dispersion 22 | - rM_sim .: lower and upper bonds of the modes to extrapolate for the simulation 23 | - f : matplotlib figure handle 24 | - ax : matplotlib axes handle 25 | - label : list of the string for each plot to be labelled 26 | - plottype : define the type of plot 'all' [defaults], 'sim', 'fit', 'fem', 'ind' 27 | 28 | ''' 29 | 30 | def __init__(self, **kwargs): 31 | cts.c = 299792458 32 | self.dispfile = kwargs.get('file', None) 33 | self.R = kwargs.get('R', 23e-6) 34 | self.f_center = kwargs.get('f_center', None) 35 | self.fpmp = kwargs.get('fpmp', None) 36 | self.D1_manual = kwargs.get('D1_manual', None) 37 | self.rM_fit = kwargs.get('rM_fit', []) 38 | self.rM_sim = kwargs.get('rM_sim', []) 39 | self.debug = kwargs.get('debug', False) 40 | self.plottype = kwargs.get('plottype', 'all') 41 | self._logger = kwargs.get('logger', None) 42 | self.pyType = kwargs.get('pyType', 'normal') 43 | self.fig = kwargs.get('fig', 'normal') 44 | assert type(self.dispfile) is str, 'Please provide a file' 45 | assert len(self.rM_fit) > 1, 'Please the modes to fit' 46 | 47 | def GetDint(self): 48 | ''' 49 | Retrieve the dispersion of a resonator based on the frequency of 50 | resonance and azimuthal mode order. The data are fit using a cubic spline method 51 | 52 | **Output** 53 | - self.PrM_fit: scipy.interpolate object which fitted the data 54 | - self.Dint_fit: fitted integrated dispersion for the simulated mode 55 | - self.neff_pmp: effective index at the pump frequency 56 | - self.ng_pmp: group index at the pump frequency 57 | ''' 58 | 59 | 60 | def getFreqModes(f_center= None): 61 | FSR0 = 1e12*23e-6/self.R 62 | lines = open(self.dispfile,'r').readlines() 63 | self.rM = np.array([float(ll.strip().split(',')[0]) for ll in lines]) 64 | self.rf = np.array([float(ll.strip().split(',')[1]) for ll in lines]) 65 | # -- Find the pumped mode -- 66 | if not f_center: 67 | pmp_ind = np.where(np.abs(self.rf-self.fpmp[0]) < 0.5*FSR0)[0] 68 | assert pmp_ind.size == 1, 'Wavelength not found!' 69 | self.pmp_ind_fit = pmp_ind[0] 70 | else: 71 | pmp_ind = np.where(np.abs(self.rf-f_center) < 0.5*FSR0)[0] 72 | assert pmp_ind.size == 1, 'Wavelength not found!' 73 | return pmp_ind[0] 74 | return self.pmp_ind_fit 75 | 76 | def getGroupIndex(): 77 | # -- Compute the effective/group index -- 78 | L = 2*np.pi*self.R 79 | df = np.gradient(self.rf) 80 | self.neff = self.rM * cts.c/(self.rf*2*np.pi*self.R) 81 | self.neff_pmp = self.neff[self.pmp_ind_fit] 82 | self.ng = cts.c/(df*L) 83 | self.ng_pmp = self.ng[self.pmp_ind_fit] 84 | self.tR = L*self.ng_pmp/cts.c 85 | 86 | def getDispersion(): 87 | # Compute the dispersion 88 | df = np.gradient(self.rf) 89 | d1_vg = np.gradient(self.ng)/cts.c 90 | D = -(self.rf**2/cts.c) * d1_vg/df 91 | self.D = D 92 | 93 | def getIntegratedDisp(ind_pmp): 94 | # -- Compute Dint -- 95 | dm = np.array([-2, -1, 0, 1, 2]) 96 | drf = self.rf - self.rf[self.pmp_ind_fit] 97 | Dfit = np.polyfit(dm, drf[ind_pmp+dm], 2) 98 | self.FSR = Dfit[1] 99 | self.D2 = Dfit[0]*2*np.pi 100 | if not self.D1_manual: 101 | D1 = self.FSR * 2*np.pi 102 | else: 103 | D1 = self.D1_manual 104 | μ = self.rM - self.rM[ind_pmp] 105 | ω = 2*np.pi*self.rf 106 | Dint = ω - (ω[ind_pmp] + D1 * μ) 107 | β2 = -self.ng_pmp/cts.c*(2*Dfit[0])/Dfit[1]**2/2/np.pi 108 | self.μ0 = μ 109 | return μ, Dint, D1 110 | 111 | def fitDintDomain(ind0,ind_master, Dint): 112 | 113 | if self.rM_fit == [None, None]: 114 | μfit = [self.μ0[0], self.μ0[-1]] 115 | shift = 0 116 | else: 117 | μfit = self.rM_fit 118 | shift = ind0 - ind_master 119 | # print(shift) 120 | μfit = [rm-shift for rm in μfit] 121 | # print(μfit) 122 | M = np.arange(ind0+μfit[0], 123 | ind0+μfit[1]+1, 124 | dtype=int) 125 | # print(M) 126 | μselect = np.arange(μfit[0],μfit[1]+1, dtype=int) 127 | assert M[0] >= 0, 'Left range for mode order not correct' 128 | assert M[-1] <= self.rM.size, 'Right range for mode order not correct' 129 | 130 | 131 | # self.PrM_fit = itp.splrep(μfit, Dint2fit) 132 | M2fit = self.rM[M] - self.rM[ind0] 133 | Dint2fit = Dint[M] 134 | fitfun = itp.splrep(M2fit, Dint2fit) 135 | fit_selected = itp.splev(μselect, fitfun) 136 | pmp_ind = np.argwhere(M2fit == 0).flatten()[0] 137 | return fitfun, μselect, fit_selected, pmp_ind 138 | 139 | def doFitSimulationDint(fitfun, ind0, ind_master): 140 | # if self.rM_fit == [None, None]: 141 | # shift = 0 142 | # else: 143 | # μfit = self.rM_fit 144 | shift = ind0 - ind_master 145 | 146 | μ2fit = [rm-shift for rm in self.rM_sim] 147 | ind_sim = np.arange(μ2fit[0], μ2fit[1]+1, dtype=int) 148 | 149 | Dint_fit = itp.splev(ind_sim, fitfun) 150 | 151 | pmp_ind = np.argwhere(ind_sim == 0).flatten()[0] 152 | 153 | return μ2fit, Dint_fit, pmp_ind 154 | 155 | 156 | 157 | # -- Get all parameters that are not relative to the pump mode -- 158 | # ---------------------------------------------------------------------------- 159 | 160 | 161 | self.μsim = [] 162 | self.Dint_fit = [] 163 | self.Dint_sim = [] 164 | self.pmp_ind = [] 165 | self.Dint = [] 166 | self.D1 = [] 167 | self.μsim = [] 168 | self.μfit = [] 169 | self.ind_pmp_sim = [] 170 | self.ind_pmp_fit = [] 171 | # -- Get all parameters that are relative to the pump mode -- 172 | # ---------------------------------------------------------------------------- 173 | # The data collected here are only entended for visulation purpose as the 174 | # integration Dint that is use in pyLLE is computed at the center of the 175 | # domain. For more information, please look at ComputeLLE.jl file (core 176 | # function in Julia of pyLLE) or chekc out Taheri et al. eq 12 177 | cnt_f = 0 178 | for ff in self.fpmp: 179 | if not ff == self.fpmp[0]: 180 | ind_pmp = getFreqModes(f_center= ff) 181 | else: 182 | ind_pmp = getFreqModes() 183 | ind_master = ind_pmp 184 | getGroupIndex() 185 | getDispersion() 186 | 187 | # will do the fit relative to the first pump 188 | μ_, Dint_, D1_ = getIntegratedDisp(ind_pmp) 189 | ff, μfit_, Dint_fit_, pmp_fit_ = fitDintDomain(ind_pmp,ind_master, Dint_) 190 | μsim_, Dint_sim_, pmp_sim_ = doFitSimulationDint(ff, ind_pmp, ind_master) 191 | 192 | self.Dint += [Dint_] 193 | self.Dint_fit += [Dint_fit_] 194 | self.Dint_sim += [Dint_sim_] 195 | self.D1 += [D1_] 196 | self.ind_pmp_sim += [pmp_sim_] 197 | self.ind_pmp_fit += [pmp_fit_] 198 | self.μsim += [μsim_] 199 | self.μfit += [μfit_] 200 | self.fpmp[cnt_f] = self.rf[ind_pmp] 201 | 202 | cnt_f += 1 203 | 204 | ff0 = self.fpmp[0] 205 | # print(μdomain) 206 | ind0 = np.sum(self.μsim[0])/2 207 | # ind1 = np.sum(self.μsim[1])/2 208 | assert ind0 == int(ind0), 'Domain not correct' 209 | ind_center = int(self.pmp_ind_fit + ind0) 210 | 211 | 212 | for ii in range(len(self.fpmp)): 213 | self.pmp_ind += [int(-1*np.sum(self.μsim[ii])/2)] 214 | 215 | 216 | f_center = self.rf[ind_center] 217 | ind_center = getFreqModes(f_center= f_center) 218 | μ_, Dint_, D1_ = getIntegratedDisp(ind_center) 219 | ff, μfit_, Dint_fit_, pmp_fit_ = fitDintDomain(ind_center,ind_center, Dint_) 220 | μsim_, Dint_sim_, pmp_sim_ = doFitSimulationDint(ff, ind_center, ind_center-ind0) 221 | 222 | self.fpmp += [f_center] 223 | self.Dint += [Dint_] 224 | self.Dint_fit += [Dint_fit_] 225 | self.Dint_sim += [Dint_sim_] 226 | self.D1 += [D1_] 227 | self.ind_pmp_sim += [pmp_sim_] 228 | self.ind_pmp_fit += [pmp_fit_] 229 | self.μsim += [μsim_] 230 | self.μfit += [μfit_] 231 | 232 | # μfit = self.μfit[ii] #+ self.ind_pmp_fit[ii] 233 | μsim = self.μsim[ii] #+ self.ind_pmp_sim[ii] 234 | self.freq_fit = self.fpmp[0] + np.arange(μsim[0], μsim[-1]+1)*self.D1[0]/(2*np.pi) 235 | 236 | # dφ = -(drf-(rM-rM[self.pmp_ind_fit])*FSR_p)/FSR_p*2*np.pi 237 | 238 | def DisplayParam(self): 239 | 240 | Info = '-- Dispersion Analysis --\n' 241 | Info += '\tPump index: {}\n'.format(self.pmp_ind_fit) 242 | Info += '\tCenter Pump: {:.3f} THz\n'.format(self.rf[self.pmp_ind_fit]*1e-12) 243 | Info += '\tFSR: {:.2f} GHz\n'.format(self.FSR*1e-9) 244 | Info += '\tD2: {:.2f} MHz\n'.format(self.D2*1e-6) 245 | print(Info) 246 | 247 | if self._logger: 248 | Info += '\t mu_fit: [{:.0f}, {:.0f}]\n'.format(self.rM_fit[0], 249 | self.rM_fit[1]) 250 | Info += '\t mu_sim: [{:.0f}, {:.0f}]\n'.format(self.rM_sim[0], 251 | self.rM_sim[1]) 252 | 253 | self._logger.info('AnalyzeDisp', Info) 254 | 255 | def DisplayPlot(self, display_center= False): 256 | 257 | def PlotJupyter(): 258 | init_notebook_mode(connected=True) 259 | trace = [] 260 | for ii in range(len(self.fpmp)-1): 261 | μfit = self.μfit[ii] #+ self.ind_pmp_fit[ii] 262 | μsim = self.μsim[ii] #+ self.ind_pmp_sim[ii] 263 | dν_fit = np.arange(μfit[0], μfit[-1]+1)*self.D1[0]/(2*np.pi) 264 | dν_sim = np.arange(μsim[0], μsim[-1]+1)*self.D1[0]/(2*np.pi) 265 | ν0 = self.fpmp[ii] 266 | rf = self.rf 267 | rf_fit = (ν0+dν_fit) 268 | rf_sim = (ν0+dν_sim) 269 | 270 | trace += [go.Scatter( 271 | x = rf*1e-12, 272 | y = (self.Dint[0] - self.Dint[0][self.ind_pmp_fit[ii]] )*1e-9/(2*np.pi), 273 | legendgroup = 'Pump #{:.0f}'.format(ii), 274 | mode = 'markers', 275 | name = 'FEM Simulation')] 276 | if self.plottype.lower() == 'all': 277 | 278 | trace += [go.Scatter( 279 | x = rf_fit*1e-12, 280 | y = (self.Dint_fit[0]- self.Dint[0][self.ind_pmp_fit[ii]])*1e-9/(2*np.pi), 281 | line = dict(width = 2, dash = 'dash'), 282 | legendgroup = 'Pump #{:.0f}'.format(ii), 283 | name = 'Fit')] 284 | trace += [go.Scatter( 285 | x = rf_sim*1e-12, 286 | y = (self.Dint_sim[0] - self.Dint[0][self.ind_pmp_fit[ii]])*1e-9/(2*np.pi), 287 | legendgroup = 'Pump #{:.0f}'.format(ii), 288 | mode = 'lines', 289 | name = 'LLE simulation')] 290 | 291 | 292 | if self.plottype.lower() == 'sim': 293 | 294 | trace += [go.Scatter( 295 | x = rf_sim*1e-12, 296 | y = self.Dint_sim[ii]*1e-9/(2*np.pi), 297 | legendgroup = 'Pump #{:.0f}'.format(ii), 298 | mode = 'lines', 299 | name = 'LLE simulation')] 300 | 301 | if self.plottype.lower() == 'fit': 302 | 303 | trace += [go.Scatter( 304 | x = rf_fit*1e-12, 305 | y = self.Dint_fit[ii]*1e-9/(2*np.pi), 306 | line = dict(width = 2, dash = 'dash'), 307 | legendgroup = 'Pump #{:.0f}'.format(ii), 308 | name = 'Fit')] 309 | if self.plottype.lower() == 'fem': 310 | pass 311 | 312 | self.fig = go.FigureWidget(data=trace) 313 | 314 | self.fig.add_hline(y=0, line_width=3,line_color="white", opacity = 1) 315 | 316 | self.fig.update_layout(xaxis = dict(title = 'Frequency (THz)'), 317 | yaxis = dict(title = 'Dint (GHz)')) 318 | 319 | def PlotMatplotlib(): 320 | self.fig, ax = plt.subplots() 321 | for ii in range(len(self.fpmp)-1): 322 | μfit = self.μfit[ii] #+ self.ind_pmp_fit[ii] 323 | μsim = self.μsim[ii] #+ self.ind_pmp_sim[ii] 324 | dν_fit = np.arange(μfit[0], μfit[-1]+1)*self.D1[0]/(2*np.pi) 325 | dν_sim = np.arange(μsim[0], μsim[-1]+1)*self.D1[0]/(2*np.pi) 326 | ν0 = self.fpmp[ii] 327 | rf = self.rf 328 | rf_fit = (ν0+dν_fit) 329 | rf_sim = (ν0+dν_sim) 330 | 331 | ax.plot(rf*1e-12, 332 | self.Dint[ii]*1e-9/(2*np.pi), 333 | 'o',ms= 3, 334 | label = 'FEM Simulation') 335 | 336 | if self.plottype.lower() == 'all': 337 | 338 | ax.plot(rf_fit*1e-12, 339 | self.Dint_fit[ii]*1e-9/(2*np.pi), 340 | '--', 341 | label = 'Fit') 342 | ax.plot(rf_sim*1e-12, 343 | self.Dint_sim[ii]*1e-9/(2*np.pi), 344 | label = 'LLE simulation') 345 | 346 | if self.plottype.lower() == 'sim': 347 | ax.plot(rf_sim*1e-12, 348 | self.Dint_sim[ii]*1e-9/(2*np.pi), 349 | label = 'LLE simulation') 350 | 351 | if self.plottype.lower() == 'fit': 352 | ax.plot(rf_fit*1e-12, 353 | self.Dint_fit[ii]*1e-9/(2*np.pi), 354 | label = 'Fit') 355 | 356 | if not self.pyType == 'jupyter': 357 | PlotMatplotlib() 358 | else: 359 | PlotJupyter() 360 | 361 | return self.fig 362 | # if __name__ == '__main__': 363 | # plt.close('all') 364 | # analyze = AnalyzeDisp(file='TestDispersion.mat', 365 | # lbd_center = 1500e-9, 366 | # rM_fit=[-50, 160], 367 | # debug=True) 368 | # analyze.GetBeta() 369 | -------------------------------------------------------------------------------- /pypiStuff/build/lib/pyLLE/_llesolver.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from ._analyzedisp import AnalyzeDisp 3 | import scipy.interpolate as itp 4 | import scipy.optimize as optm 5 | import scipy.fftpack as fft 6 | from scipy import constants as cts 7 | import matplotlib.pyplot as plt 8 | import time 9 | import sys 10 | import subprocess as sub 11 | import os 12 | import inspect 13 | from copy import copy 14 | import pickle as pkl 15 | import shutil 16 | import tempfile 17 | from prettytable import PrettyTable 18 | import warnings 19 | import matplotlib as mpl 20 | import matplotlib.gridspec as gridspec 21 | from matplotlib import ticker 22 | import matplotlib.font_manager as font_manager 23 | from datetime import datetime 24 | from prettytable import PrettyTable 25 | from plotly import tools 26 | from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot 27 | import plotly.graph_objs as go 28 | 29 | with warnings.catch_warnings(): 30 | warnings.filterwarnings("ignore", category=FutureWarning) 31 | import h5py 32 | import ipdb 33 | 34 | 35 | backend = mpl.get_backend() 36 | path_juliaScript = os.path.dirname(os.path.abspath(__file__)) 37 | path_juliaScript = os.path.join(path_juliaScript, 'ComputeLLE.jl') 38 | 39 | print('*'*60) 40 | print('Julia solver:') 41 | print(path_juliaScript) 42 | print('*'*60) 43 | 44 | 45 | 46 | # delete folder as the temp file will not be in it but will be used as a prefix 47 | # print('-'*50) 48 | # print('Path to temporary dir to save .h5 files with prefix:') 49 | # print(tmp_dir) 50 | # print('-'*50) 51 | # print('Path to Julia script: ') 52 | # print(path_juliaScript) 53 | # print('-'*50) 54 | 55 | 56 | main_tmp_dir = tempfile.mkdtemp() 57 | # Check which type of python we are launching 58 | 59 | try: 60 | className = get_ipython().__class__.__name__ 61 | if className == 'ZMQInteractiveShell': 62 | pyType = 'jupyter' 63 | elif className == 'TerminalInteractiveShell': 64 | pyType = 'ipython' 65 | except: 66 | # launching trhough a normal python 67 | pyType = 'normal' 68 | 69 | # print(pyType) 70 | 71 | 72 | class MyLogger(): 73 | ''' 74 | Custom made logger as the logger default package cannot be pickled 75 | ''' 76 | 77 | def __init__(self, fname): 78 | self.fname = fname 79 | open(self.fname,'a').write('\n' + '-'*75 + '\n') 80 | 81 | def info(self, method, message): 82 | time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") 83 | mess = '[ ' + time + ' - ' + method + ' ] ' + message + '\n' 84 | open(self.fname,'a').write(mess) 85 | 86 | class Latexify(): 87 | ''' 88 | Class that handle saving the figures in a nice way compatible with 89 | the column/page size of different latex template 90 | 91 | input [] = optional: 92 | - figname = name to save the figure (without extension) 93 | - 94 | - fig = matplotlib handle to the figure 95 | - [fig_width]: default = 1column 96 | - [frmt]: default = pdf 97 | - [fig_height] : default = 6.5 98 | - [font_size] : default = 8 99 | ''' 100 | __author__ = "Gregory Moille" 101 | __copyright__ = "Copyright 2018, NIST" 102 | __credits__ = ["Gregory Moille", 103 | "Kartik Srinivasan"] 104 | __license__ = "GPL" 105 | __version__ = "2.0.1" 106 | __maintainer__ = "Gregory Moille" 107 | __email__ = "gregory.moille@nist.gov" 108 | __status__ = "Development" 109 | 110 | def __init__(self, **kwarg): 111 | # get parameters 112 | figname = kwarg.get('figname', '') 113 | fig = kwarg.get('fig', None) 114 | fig_width = kwarg.get('fig_width', '1column') 115 | self.frmt = kwarg.get('frmt', 'pdf') 116 | self.fig_height = kwarg.get('fig_height', 6.5) 117 | self.font_size = kwarg.get('font_size', 8) 118 | if isinstance(fig_width, str): 119 | if fig_width.lower() == '1column': 120 | self.fig_width = 8.6 121 | elif fig_width.lower() == '2column': 122 | self.fig_width = 14 123 | if fig_width.lower() == '1columnbeamer': 124 | self.fig_width = 10.79846 / 2 125 | if not kwarg.get('fig_height', False): 126 | self.fig_height = 6.5 * 10.79846 / 24 127 | if fig_width.lower() == '2columnbeamer': 128 | self.fig_width = 10.79846 129 | if not kwarg.get('fig_height', False): 130 | self.fig_height = 6.5 * 10.79846 / 14 131 | else: 132 | self.fig_width = fig_width 133 | 134 | inch = 2.54 135 | self.fig_width = self.fig_width / inch 136 | self.fig_height = self.fig_height / inch 137 | self.f = fig 138 | self.figname = figname 139 | self.SavePlot() 140 | 141 | def SavePlot(self): 142 | # -- Define Font Properties -- 143 | # ----------------------------------------------------- 144 | # fontpath = '/System/Library/Fonts' 145 | font_prop = font_manager.FontProperties(size=8) 146 | plt.ion() 147 | # -- Define Param of Plot -- 148 | # ----------------------------------------------------- 149 | params = {'backend': 'ps', 150 | 'text.latex.preamble': [r'\usepackage{gensymb}', 151 | r'\usepackage{siunitx}', 152 | r'\sisetup{detect-all}', 153 | r'\usepackage{helvet}', 154 | r'\usepackage{sansmath}', 155 | r'\sansmath', ], 156 | 'text.latex.unicode': False, 157 | # fontsize for x and y labels(was 10) 158 | 'axes.labelsize': self.font_size, 159 | 'axes.titlesize': self.font_size, 160 | 'axes.linewidth': 0.5, 161 | 'xtick.major.width': 1, 162 | 'xtick.minor.width': 1, 163 | 'ytick.major.width': 1, 164 | 'ytick.minor.width': 1, 165 | 'legend.fontsize': self.font_size, # was 10 166 | 'xtick.labelsize': self.font_size, 167 | 'ytick.labelsize': self.font_size, 168 | 'text.usetex': False, 169 | 'figure.figsize': [self.fig_width, self.fig_height], 170 | # 'font.family': 'sans-serif', 171 | 'font.size': self.font_size, 172 | 'lines.linewidth': 0.25, 173 | } 174 | mpl.rcParams.update(params) 175 | 176 | plt.pause(0.1) 177 | self.f.set_facecolor('None') 178 | # -- Redo Font -- 179 | # ----------------------------------------------------- 180 | for ax in self.f.axes: 181 | ax.xaxis.set_ticks_position('both') 182 | ax.yaxis.set_ticks_position('both') 183 | 184 | for line in ax.yaxis.get_ticklines(): 185 | line.set_markeredgewidth(0.25) 186 | line.set_markersize(3) 187 | plt.tick_params(which='minor', length=2, width=0.25) 188 | 189 | for line in ax.xaxis.get_ticklines(): 190 | line.set_markeredgewidth(0.25) 191 | line.set_markersize(3) 192 | for tick in ax.xaxis.get_major_ticks(): 193 | tick.label.set_fontsize(self.font_size) 194 | for tick in ax.yaxis.get_major_ticks(): 195 | tick.label.set_fontsize(self.font_size) 196 | for axis in ['top', 'bottom', 'left', 'right']: 197 | ax.spines[axis].set_visible(True) 198 | ax.spines[axis].set_edgecolor('k') 199 | ax.spines[axis].set_linewidth(0.25) 200 | ax.axesPatch.set_facecolor('None') 201 | 202 | # ax.grid('off') 203 | xstr = ax.get_xlabel() 204 | ax.set_xlabel(xstr, size=self.font_size) 205 | ystr = ax.get_ylabel() 206 | ax.set_ylabel(ystr, size=self.font_size) 207 | leg = ax.axes.get_legend() 208 | # Check if ther is a legend 209 | # ---------------------------------------- 210 | if leg: 211 | txt = leg.properties()['texts'] 212 | lbl_lines = leg.properties()['lines'] 213 | for ii in txt: 214 | ii.set_fontsize(self.font_size) 215 | for ii in lbl_lines: 216 | ii.set_linewidth(0.25) 217 | #change linestyle for line2D 218 | for ch in ax.get_children(): 219 | if type(ch) == mpl.lines.Line2D: 220 | ch.set_linewidth(0.25) 221 | ch.set_markersize(2) 222 | ch.set_markeredgewidth(4) 223 | ch.set_markeredgecolor('None') 224 | # -- Update plot -- 225 | # ----------------------------------------------------- 226 | self.f.set_size_inches(self.fig_width, self.fig_height) 227 | self.f.canvas.draw() 228 | plt.draw() 229 | plt.pause(0.05) 230 | if not self.figname == '': 231 | self.f.savefig(self.figname + '.' + self.frmt, format = self.frmt) 232 | plt.pause(0.05) 233 | self.GoBackToNormal() 234 | plt.ioff() 235 | 236 | def GoBackToNormal(self): 237 | file = mpl.get_data_path() + '/matplotlibrc' 238 | mpl.rcParams.update(mpl.rc_params_from_file( 239 | file)) 240 | self.f.canvas.draw() 241 | 242 | class LLEsolver(object): 243 | ''' 244 | Class to solve the Lugiato Lefever Equation 245 | Initialization input ([]=facultative): 246 | 247 | **res ** 248 | 249 | - Qi : intrinsic Q of the resonator 250 | - Qc : coupling Q of the resonator 251 | - R : ring radius 252 | - gamma : Non linear index of the material 253 | - dispfile : str pointing to a .csv file where the azimuthal mode orders and corresponding resonances are saved 254 | 255 | **sim ** 256 | 257 | - Tscan : length of the simulation (in unit of round trip) 258 | - mu_fit : number of mode to fit 259 | - mu_sim : number of mode to simulate 260 | - domega_init : initial detuning of the pump 261 | - domega_end : final detuning of the pump 262 | - [domega_stop] : where to stop the scan in detuning but keep doing the simulation 263 | 264 | **debug **: Save a trace in a logfile in the working directory of the different actions pyLLE perform (default = False) 265 | ''' 266 | _c0 = 299792458 267 | hbar = 6.634e-34/(2*np.pi) 268 | __author__ = "Gregory Moille" 269 | __copyright__ = "Copyright 2018, NIST" 270 | __credits__ = ["Gregory Moille", 271 | "Qing Li", 272 | "Xiyuan Lu", 273 | "Kartik Srinivasan"] 274 | __license__ = "GPL" 275 | __version__ = "1.0.0" 276 | __maintainer__ = "Gregory Moille" 277 | __email__ = "gregory.moille@nist.gov" 278 | __status__ = "Development" 279 | 280 | def __init__(self, **kwargs): 281 | self._res = kwargs.get('res', {}) 282 | self._sim = kwargs.get('sim', {}) 283 | # self._sim_norm = kwargs.get('sim_norm', None) 284 | self._debug = kwargs.get('debug', False) 285 | self._plotPower = None 286 | self._plotSpecta = None 287 | self._indSpectra = 0 288 | self._plotTime = None 289 | self._indTime = 0 290 | 291 | # find all the needed parameters 292 | # ------------------------------------------------------------ 293 | assert 'Qi' in self._res.keys(), 'Please provide Qi' 294 | assert 'Qc' in self._res.keys(), 'Please provide Qc' 295 | assert 'R' in self._res.keys(), 'Please provide R' 296 | assert 'Tscan' in self._sim.keys(), 'Please provide Tscan' 297 | assert 'dispfile' in self._res.keys(), 'Please provide dispfile' 298 | 299 | if not "D1_manual" in self._sim.keys(): 300 | self._sim["D1_manual"] = None 301 | 302 | # -- check if wavelength or frequency 303 | # ------------------------------------------------------------ 304 | if not('f_pmp' in self._sim.keys()): 305 | self._sim['f_pmp'] = self._c0/self._sim['lbd_pmp'] 306 | if not('mu_fit' in self._sim.keys()): 307 | self._sim['mu_fit'] = [None, None] 308 | 309 | 310 | # -- Make sur than each pump has a power -- 311 | if not type(self._sim['f_pmp'])==list: 312 | self._sim['f_pmp']= [self._sim['f_pmp']] 313 | if not type(self._sim['Pin'])==list: 314 | self._sim['Pin']= [self._sim['Pin']] 315 | assert len(self._sim['Pin']) == len(self._sim['f_pmp']), "The number of *pump* and *pump power* has to be the same" 316 | 317 | 318 | 319 | 320 | # -- Translate the dict from greek sign =-- 321 | # ------------------------------------------------------------ 322 | self._sim = self._Translator(self._sim) 323 | self._res = self._Translator(self._res) 324 | 325 | 326 | # -- Fix missing keys -- 327 | # ------------------------------------------------------------ 328 | if not ('domega_stop' or 'δω_stop') in self._sim.keys(): 329 | try: 330 | self._sim['domega_stop'] = self._sim['domega_end'] 331 | 332 | except: 333 | self._sim['δω_stop'] = self._sim['δω_end'] 334 | 335 | 336 | 337 | if not np.diff(self._sim['mu_sim'])[0] % 2 == 0: 338 | print(r"/!\ Simulation modes length need to be odd") 339 | print('Modification of the simulation modes suchat that:') 340 | self._sim['mu_sim'] = [self._sim['mu_sim'][0], self._sim['mu_sim'][1]+1] 341 | print('μ_sim = [{:.0f} {:.0f}]'.format(self._sim['mu_sim'][0], 342 | self._sim['mu_sim'[1]] )) 343 | 344 | 345 | # -- handle the detuning of aux pump-- 346 | # ------------------------------------------------------------ 347 | if not 'domega' in self._sim.keys(): 348 | self._sim['domega'] = [0]*len(self._sim['f_pmp']) 349 | self._sim['ind_pump_sweep'] = 0 350 | else: 351 | domega = self._sim['domega'] 352 | id_sweep = [ii for ii in range(len(domega)) if domega[ii] == None] 353 | assert len(id_sweep)>=1, 'Need to provide at least None possition in domega to determine which pump is swept' 354 | 355 | self._sim['ind_pump_sweep'] = id_sweep 356 | assert len(self._sim['f_pmp']) == len(self._sim['domega']), "Please provide the same number of pump fixed detuning than pump frequencies. Detuning = None for the pump which is swept" 357 | assert len(self._sim['Pin']) == len(self._sim['domega']), "Please provide the same number of pump fixed detuning than pump power. Detuning = None for the pump which is swept" 358 | 359 | if not type(self._sim['ind_pump_sweep'])==list: 360 | self._sim['ind_pump_sweep'] = [self._sim['ind_pump_sweep']] 361 | 362 | # -- handle the phase of the pump-- 363 | # ------------------------------------------------------------ 364 | if not 'phi_pmp' in self._sim.keys(): 365 | self._sim['phi_pmp'] = [0]*len(self._sim['f_pmp']) 366 | else: 367 | if not type(self._sim['phi_pmp'])==list: 368 | self._sim['phi_pmp'] = [self._sim['phi_pmp']] 369 | assert len(self._sim['f_pmp']) == len(self._sim['phi_pmp']), "Please provide the same number of pump phase than pump frequencies. Detuning = None for the pump which is swept" 370 | 371 | 372 | 373 | # -- Setup the Logger --- 374 | # ------------------------------------------------------------ 375 | if self._debug: 376 | self._logger = MyLogger("LLE.log") 377 | self._logger.info('__init__', 'New LLE') 378 | else: 379 | self._logger = None 380 | 381 | def _Translator(self,D): 382 | Dnew = {} 383 | self._did_translate = False 384 | self._greek ={'α': 'alpha', 385 | 'β':'beta', 386 | 'γ': 'gamma', 387 | 'ω': 'omega', 388 | 'δ': 'd', 389 | 'Δ': 'D', 390 | 'μ': 'mu', 391 | 'λ': 'lambda', 392 | 'ε': 'epsilon', 393 | 'φ': 'phi'} 394 | for k in D.keys(): 395 | new_k = '' 396 | for char in list(k): 397 | if char in list(self._greek.keys()): 398 | self._did_translate = True 399 | new_k += self._greek[char] 400 | else: 401 | new_k += char 402 | Dnew[new_k] = D[k] 403 | 404 | return Dnew 405 | 406 | def Analyze(self, plot=True, display_center = True, label=None, plottype='all', verbose = False): 407 | ''' 408 | Call pyLLE.analyzedisp.AnalyzeDisp to get the dispersion of the resonator we want to simulate 409 | ''' 410 | 411 | fig = None 412 | 413 | 414 | if self._debug: 415 | Info = '\n\tFilename: {}\n'.format(self._res['dispfile']) 416 | for ff in self._sim['f_pmp']: 417 | Info += '\tf_pmp: {:.3f} THz'.format(ff*1e-12) 418 | self._logger.info('LLEsovler.Analyze', "Analyzing dispersion file" + Info) 419 | 420 | 421 | # -- Initialized usufu diserspions data -- 422 | # ------------------------------------------------------------ 423 | self._sim['ind_pmp'] = [] 424 | self._sim['Dint'] = [] 425 | # self._res['ng'] = [] 426 | # self._res['neff'] = [] 427 | 428 | 429 | 430 | # -- Get dispersion for each pump -- 431 | # ------------------------------------------------------------ 432 | # for ff in self._sim['f_pmp']: 433 | fpmp = copy(self._sim['f_pmp']) 434 | self._analyze = AnalyzeDisp(file= self._res['dispfile'], 435 | fpmp = fpmp, 436 | rM_fit = self._sim['mu_fit'], 437 | rM_sim = self._sim['mu_sim'], 438 | R = self._res['R'], 439 | D1_manual = self._sim["D1_manual"], 440 | fig = fig, 441 | plottype = plottype, 442 | logger = self._logger, 443 | pyType = pyType) 444 | 445 | self._analyze.GetDint() 446 | # if verbose: 447 | # self._analyze.DisplayParam() 448 | if plot: 449 | fig = self._analyze.DisplayPlot(display_center) 450 | 451 | 452 | # 453 | self._sim['Dint'] = self._analyze.Dint_sim[0] 454 | self._sim['D1'] = self._analyze.D1[0] 455 | self._res['ng'] = self._analyze.ng_pmp 456 | self._sim['ind_pmp'] = self._analyze.pmp_ind 457 | self._sim['f_center'] = self._analyze.fpmp[-1] 458 | self._sim['f_pmp'] = self._analyze.fpmp[:-1] 459 | self._sim['mu_sim_center'] = [self._sim['mu_sim'][0]+self._sim['ind_pmp'][0], 460 | self._sim['mu_sim'][1]+self._sim['ind_pmp'][0]] 461 | self._sim['D1_center'] = self._analyze.D1[-1] 462 | self._sim['FSR'] = [dd/(2*np.pi) for dd in self._analyze.D1[:-1]] 463 | self._sim['FSR_center'] = self._analyze.D1[-1]/(2*np.pi) 464 | 465 | 466 | 467 | if not "DKS_init" in self._sim.keys(): 468 | self._sim['DKS_init']= np.zeros(self._analyze.Dint_sim[0].size) 469 | 470 | 471 | disp = { 472 | 'ng': self._analyze.ng, 473 | 'D': self._analyze.D*1e6, 474 | "D1": self._analyze.D1[0], 475 | 'neff': self._analyze.neff, 476 | 'freq': self._analyze.rf, 477 | 'freq_sim': self._analyze.freq_fit, 478 | 'Dint': self._analyze.Dint[:-1], 479 | 'Dint_sim': self._analyze.Dint_sim[:-1], 480 | 'Dint0': self._analyze.Dint_sim[-1], 481 | 'FSR': self._sim['FSR'], 482 | 'FSR_center': self._sim['FSR_center'] 483 | } 484 | 485 | res = { 486 | 'R': self._res['R'], 487 | 'Qi': self._res['Qi'], 488 | 'Qc': self._res['Qc'], 489 | 'γ': self._res['gamma'], 490 | 'dispfile': self._res['dispfile'], 491 | } 492 | 493 | sim = { 494 | "Pin": self._sim['Pin'], 495 | "Tscan": self._sim['Tscan'], 496 | "f_pmp": self._sim['f_pmp'], 497 | "f_center": self._sim['f_center'], 498 | "δω_init": self._sim['domega_init'], 499 | "δω_end": self._sim['domega_end'], 500 | "δω": self._sim['domega'], 501 | "μ_sim": self._sim['mu_sim'], 502 | "μ_fit": self._sim['mu_fit'], 503 | "μcenter": int(-1*self._sim['mu_sim_center'][0]), 504 | "ind_pmp": self._sim['ind_pmp'], 505 | "ind_pump_sweep": self._sim['ind_pump_sweep'], 506 | "phi_pmp": self._sim['phi_pmp'], 507 | "DKS_init": self._sim['DKS_init'], 508 | } 509 | 510 | 511 | 512 | did_translate = not(self._did_translate) 513 | 514 | if not self._did_translate: 515 | sim = self._Translator(sim) 516 | 517 | self.sim = _dic2struct(sim,which = 'sim', do_tr = did_translate) 518 | self.disp = _dic2struct(disp,which = 'disp', do_tr = did_translate) 519 | self.res = _dic2struct(res, which = 'res', do_tr = did_translate) 520 | 521 | return fig 522 | 523 | def Setup(self, tmp_dir = None, verbose = False): 524 | ''' 525 | Setup the simulation for the Julia back-end. 526 | Save the two main dictionary self._sim and self._res into a readable hdf5 file for Julia in the temporary location define by the os 527 | ''' 528 | if tmp_dir == None: 529 | self.tmp_dir = main_tmp_dir 530 | # os.rmdir(os.path.join(tmp_dir') 531 | else: 532 | self.tmp_dir = tmp_dir 533 | 534 | def CleanUpHDF5(): 535 | 536 | try: 537 | os.remove(self.tmp_dir + 'ParamLLEJulia.h5') 538 | except: 539 | pass 540 | 541 | try: 542 | os.remove(self.tmp_dir + 'ResultsJulia.h5') 543 | except: 544 | pass 545 | try: 546 | os.remove(self.tmp_dir + 'log.log') 547 | except: 548 | pass 549 | 550 | def LoggerDic(): 551 | dic_sim = {'Pin': ('Pin',1e3, 'mW'), 552 | 'Tscan': ('Tscan',1e-6, 'x1e6 Round Trip'), 553 | 'domega_init': (u'\u03B4\u03C9_init',1e-9/(2*np.pi), u'x2\u03C0 GHz'), 554 | 'domega_end': (u'\u03B4\u03C9_end',1e-9/(2*np.pi), u'x2\u03C0 GHz'), 555 | 'domega_stop': (u'\u03B4\u03C9_stop',1e-9/(2*np.pi), u'x2\u03C0 GHz'), 556 | 'f_pmp': ('f_pmp',1e-12, 'THz'), 557 | 'domega_aux': (u'\u03B4\u03C9_aux',1e-9/(2*np.pi), u'x2\u03C0 GHz'), 558 | 'ind_pump_sweep': ('ind_pump_sweep',1, ''), 559 | 'mu_sim': (u'\u03BC_sim',1, ''), 560 | 'mu_fit': (u'\u03BC_fit',1, ''),} 561 | 562 | try: 563 | if len(self._res['Qc']) >1: 564 | dic_res = {'R': ('R',1e6, 'µm'), 565 | 'Qi': ('Qi',1e-6, 'M'), 566 | 'gamma': (u'\u03B3', 1, ''),} 567 | else: 568 | dic_res = {'R': ('R',1e6, 'µm'), 569 | 'Qi': ('Qi',1e-6, 'M'), 570 | 'Qc': ('Qc',1e-6, 'M'), 571 | 'gamma': (u'\u03B3', 1, ''),} 572 | except: 573 | dic_res = {'R': ('R',1e6, 'µm'), 574 | 'Qi': ('Qi',1e-6, 'M'), 575 | 'Qc': ('Qc',1e-6, 'M'), 576 | 'gamma': (u'\u03B3', 1, ''),} 577 | 578 | return dic_sim, dic_res 579 | 580 | def PrintLogger(dic_sim, dic_res): 581 | self._sim['debug'] = int(self._debug) 582 | Info = '-- Solving standard LLE --\n' 583 | Info += '\tSimulation Parameters\n' 584 | for k, it in self._res.items(): 585 | if k in dic_res.keys(): 586 | if it == None: 587 | Info +='\t\t{} = {}\n'.format(dic_res[k][0], 'None') 588 | else: 589 | Info +='\t\t{} = {:.2f} {}\n'.format(dic_res[k][0], it*dic_res[k][1],dic_res[k][2]) 590 | 591 | 592 | Info += '\tSimulation Parameters\n' 593 | for k, it in self._sim.items(): 594 | if k in dic_sim.keys(): 595 | if type(it) is list: 596 | if dic_sim[k][0] == u'\u03BC_sim' or dic_sim[k][0] == u'\u03BC_fit': 597 | if it == [None, None]: 598 | Info += '\t\t{} = [None,None] {}\n'.format(dic_sim[k][0], 599 | dic_sim[k][2]) 600 | else: 601 | Info += '\t\t{} = [{:.2f},{:.2f}] {}\n'.format(dic_sim[k][0], 602 | it[0]*dic_sim[k][1], 603 | it[1]*dic_sim[k][1], 604 | dic_sim[k][2]) 605 | else: 606 | cnt = 0 607 | for iitt in it: 608 | if iitt == None: 609 | Info += '\t\t{}[{}] = {}\n'.format(dic_sim[k][0], 610 | cnt, 611 | 'None') 612 | else: 613 | Info += '\t\t{}[{}] = {:.2f} {}\n'.format(dic_sim[k][0], 614 | cnt, 615 | iitt*dic_sim[k][1], 616 | dic_sim[k][2]) 617 | cnt += 1 618 | else: 619 | if it == None: 620 | Info +='\t\t{} = {} {}\n'.format(dic_sim[k][0], 'None',dic_sim[k][2]) 621 | else: 622 | Info +='\t\t{} = {:.2f} {}\n'.format(dic_sim[k][0], it*dic_sim[k][1],dic_sim[k][2]) 623 | 624 | print(Info) 625 | if self._debug: 626 | try: 627 | self._logger.info('LLEsovler.Setup', Info) 628 | except: 629 | Info = ''.join([self._greek[ii] if ii in self._greek.keys() else ii for ii in Info]) 630 | self._logger.info('LLEsovler.Setup', Info) 631 | 632 | def SetupHDF5(): 633 | # -- create h5file -- 634 | if verbose: 635 | print('HDF5 parameter file can be foud in: {}'.format(self.tmp_dir + 'ParamLLEJulia.h5')) 636 | h5f = h5py.File(self.tmp_dir + 'ParamLLEJulia.h5', 'w') 637 | if self._debug: 638 | self._logger.info('LLEsovler.Setup','Saving parameters in: {}'.format(self.tmp_dir + 'ParamLLEJulia.h5')) 639 | 640 | 641 | h5f.create_group('sim') 642 | h5f.create_group('res') 643 | 644 | for key, it in self._sim.items(): 645 | if not key == 'domega_disp': 646 | if type(it) is str: 647 | it = np.string_(it) 648 | if type(it) is list: 649 | try: 650 | if None in it: 651 | it = [0 if iitt is None else iitt for iitt in it] 652 | except: 653 | pass 654 | else: 655 | 656 | try: 657 | if it == None: 658 | it = 0 659 | except: 660 | pass 661 | dset = key 662 | h5f.create_dataset(f'sim/{dset}', data=[it]) 663 | if key == "DKS_init": 664 | 665 | dset = 'DKSinit_real' 666 | h5f.create_dataset(f'sim/{dset}', data=np.real(it)) 667 | dset = 'DKSinit_imag' 668 | h5f.create_dataset(f'sim/{dset}', data=np.imag(it)) 669 | 670 | 671 | 672 | 673 | for key, it in self._res.items(): 674 | if not key == 'domega_disp': 675 | if type(it) is str: 676 | it = np.string_(it) 677 | if type(it) is list: 678 | if None in it: 679 | it = [0 if iitt is None else iitt for iitt in it] 680 | else: 681 | if it == None: 682 | it = 0 683 | h5f.create_dataset('res/{}'.format(key), data=[it]) 684 | h5f.close() 685 | 686 | 687 | 688 | # delay a bit the start 689 | time.sleep(0.5) 690 | CleanUpHDF5() 691 | # make sure the cleanup happened 692 | time.sleep(1) 693 | dic_sim, dic_res = LoggerDic() 694 | if verbose or self._debug: 695 | PrintLogger(dic_sim, dic_res) 696 | SetupHDF5() 697 | 698 | def SolveTemporal(self, verbose = False, tol = 1e-3, maxiter = 6, step_factor = 0.1): 699 | ''' 700 | Call Julia to solve the LLE 701 | ''' 702 | self._solver = 'temporal' 703 | 704 | 705 | def DisplaySim(): 706 | 707 | if self._debug: 708 | self._logger.info('LLEsovler.SolveTemporal','Solving Temporal LLE with Julia....') 709 | Info = 'tol = {} -- maxiter = {} step_factpr = {}'.format(tol, maxiter, step_factor) 710 | self._logger.info('LLEsovler.SolveTemporal',Info) 711 | 712 | 713 | hLine = '-'*70 714 | 715 | print(hLine) 716 | 717 | date = time.localtime() 718 | date = "{}-{:0>2}-{:0>2} ".format(date.tm_year, 719 | date.tm_mon, 720 | date.tm_mday) +\ 721 | "{:0>2}:{:0>2}:{:0>2}".format(date.tm_hour, 722 | date.tm_min, 723 | date.tm_sec) 724 | 725 | print(date) 726 | 727 | def LaunchJulia(): 728 | 729 | if sys.platform == 'darwin': 730 | julia = 'julia' 731 | if sys.platform == 'linux2' or sys.platform == 'linux': 732 | julia = 'julia' 733 | if sys.platform == 'win32': 734 | julia = os.path.expanduser('~') + '\\AppData\\Local\\Julia-1.1.1\\bin\\julia.exe' 735 | 736 | command = [julia, path_juliaScript , self.tmp_dir, str(tol), str(maxiter), str(step_factor)] 737 | self.JuliaSolver = sub.Popen(command, stdout=sub.PIPE, stderr=sub.PIPE) 738 | fname = self.tmp_dir + 'log.log' 739 | if verbose: 740 | print('Launching Julia....') 741 | print('Temp file can be found in: {}'.format(fname)) 742 | 743 | start = time.time() 744 | return fname, start 745 | 746 | def Pbar(perc, pgrs, tb_up, conv_err): 747 | bar_width = 50 748 | pgrs = '*'*int(np.floor(perc/2)) 749 | width = ' '* (bar_width - len(pgrs)) 750 | perc_str = ' {}%'.format(perc) 751 | line = 'Computing LLE [' + pgrs + width + ']' + perc_str 752 | if conv_err: 753 | line = line + ' /!\ Convergence issue' 754 | if self._debug: 755 | self._logger.info('LLEsovler.SolveTemporal','/!\ Convergence issue') 756 | length = len(line) 757 | return line, length, pgrs, tb_up 758 | 759 | def ProbeProgress(fname, start): 760 | tb_up = 2 761 | pgrs = '' 762 | perc_old = -1 763 | perc = -1 764 | conv_err = False 765 | line = '' 766 | timenow = time.time() 767 | # wait for the solver to actually start 768 | while not perc == 0 and self.JuliaSolver.poll() == None: 769 | try: 770 | perc = int(open(fname).readlines()[-1].strip()) 771 | except Exception as e: 772 | pass 773 | # print('line 654') 774 | # print(e) 775 | 776 | #fetch if any errors: 777 | err = False 778 | if not self.JuliaSolver.poll() == None: 779 | _, err = self.JuliaSolver.communicate() 780 | if not err.decode() == '': 781 | print('!!! JULIA ERROR !!!') 782 | print(err.decode()) 783 | err = True 784 | print("Error: {}".format(err)) 785 | 786 | if not err: 787 | if verbose: 788 | print('Launching Julia: Done') 789 | perc = -1 790 | while not perc == 100 and self.JuliaSolver.poll() == None: 791 | try: 792 | ll = open(fname).readlines()[-1].strip() 793 | try: 794 | perc = int(ll) 795 | if not perc_old == perc: 796 | line, length, pgrs, tb_up= Pbar(perc, pgrs, tb_up, conv_err) 797 | print('\r' + line, end = '') 798 | perc_old = perc 799 | 800 | except Exception as e: 801 | print('line 681') 802 | print(e) 803 | if ll.split()[0] == 'Failed': 804 | conv_err = True 805 | 806 | except Exception as e: 807 | print('line 686') 808 | print(e) 809 | pass 810 | time.sleep(1) 811 | line, length, pgrs, tb_up= Pbar(100, pgrs, tb_up, conv_err) 812 | time_taken = time.time() - start 813 | end = time.time() 814 | hours, rem = divmod(end-start, 3600) 815 | minutes, seconds = divmod(rem, 60) 816 | time_taken = "Simulation Time " + \ 817 | "{:0>2}h:{:0>2}min:{:0>4.1f}s".format(int(hours), 818 | int(minutes), 819 | seconds) 820 | print('\n') 821 | print(time_taken) 822 | print('-'*70) 823 | if self._debug: 824 | self._logger.info('LLEsovler.SolveTemporal', time_taken) 825 | 826 | DisplaySim() 827 | time.sleep(2) 828 | JuliaLog, start_time = LaunchJulia() 829 | ProbeProgress(JuliaLog, start_time) 830 | 831 | def SolveSteadyState(self, do_plot = True): 832 | ''' 833 | Newton Method to find the root of the steady state equation 834 | ''' 835 | 836 | self._solver = 'steady' 837 | if self._debug: 838 | self._logger.info('LLEsovler.SolveSteadySteate','Solving Steady State LLE with Python....') 839 | print('-'*70) 840 | date = time.localtime() 841 | date = "{}-{:0>2}-{:0>2} ".format(date.tm_year, 842 | date.tm_mon, 843 | date.tm_mday) +\ 844 | "{:0>2}:{:0>2}:{:0>2}".format(date.tm_hour, 845 | date.tm_min, 846 | date.tm_sec) 847 | start = time.time() 848 | print(date) 849 | 850 | # -- CHeck Parity of the µ -- 851 | μ_sim = copy(self._sim['mu_sim']) 852 | ind = 0 853 | if not μ_sim[0] == -μ_sim[1]: 854 | μ_sim = [-np.max(np.abs(μ_sim)), np.max(np.abs(μ_sim))] 855 | INFO = 'Not symmetric mode calculation -> switching to it with µ_sim = {}\n'.format(μ_sim) 856 | print(INFO) 857 | if self._debug: 858 | try: 859 | self._logger.info('LLEsovler.SolveSteadySteate',INFO) 860 | except: 861 | Info = ''.join([self._greek[ii] if ii in self._greek.keys() else ii for ii in Info]) 862 | self._logger.info('LLEsovler.SolveSteadySteate',INFO) 863 | 864 | dum = self.Analyze(mu_sim = μ_sim, plot = False, f = None) 865 | 866 | 867 | # -- setting up parameters -- 868 | β2 = self._analyze.β2 869 | Pin = self._sim['Pin'] 870 | γ = self._res['gamma'] 871 | L = 2*np.pi*self._res['R'] 872 | ω0 = self._sim['f_pmp'][0]*2*np.pi 873 | Q0 = self._res['Qi'] 874 | Qc = self._res['Qc'] 875 | tR = L*self._res['ng']/self._c0 876 | α = 1/2 * (ω0/Q0 + ω0/Qc) * tR 877 | θ = ω0/Qc*tR 878 | δω = -self._sim['domega']* tR 879 | 880 | nlc = -1j*γ*L 881 | μ = np.arange(μ_sim[0], μ_sim[1]+1) 882 | pmp_ind = np.where(μ == 0)[0][0] 883 | ω = μ*2*np.pi/tR + ω0 884 | ν = ω/(2*np.pi) 885 | # -- setting up input power -- 886 | Ein = np.zeros(μ.size) 887 | Ein[pmp_ind] = np.sqrt(Pin) * μ.size 888 | Ein_couple = np.sqrt(θ)*Ein 889 | 890 | # -- Define Initial Guess -- 891 | sech = lambda x: 1/np.cosh(x) 892 | η = δω/α # need to be fixed 893 | B0 = np.sqrt(2*η) 894 | f = np.sqrt(θ* Pin* γ* L/α**3) 895 | φ0 = np.arccos(np.sqrt(8*η)/np.pi/f) 896 | τ = np.linspace(-0.5,0.5, μ.size)*tR 897 | Φ0 = f/η**2 -1j* f/η 898 | ut0 = np.sqrt(α/γ/L) * (Φ0+ B0 * np.exp(1j*φ0) * sech(0.5*B0*np.sqrt(α/(np.abs(β2)*L))*τ)) 899 | Em0 = fft.fftshift(fft.fft(ut0)) 900 | x_init = np.concatenate((Em0.real, -Em0.imag)) 901 | 902 | # -- Define the Steady State LLE Equation -- 903 | φ = -α + 1j*δω - 1j*self._sim["dphi"] 904 | Em= lambda xx: xx[0:int(xx.shape[0]/2)] + 1j*xx[int(xx.shape[0]/2)] 905 | Ut= lambda xx: fft.ifft(Em(xx)); 906 | fm= lambda xx: φ*Em(xx) + nlc*fft.fft(np.abs(Ut(xx))**2*Ut(xx)) + Ein_couple; 907 | fvec= lambda xx: np.concatenate((fm(xx).real, fm(xx).imag)) 908 | 909 | # -- Solver the Steady State -- 910 | out = optm.root(fvec, x_init, method='lm', jac=None, tol=1e-8) 911 | Ering = Em(out.x)/μ.size 912 | Ewg = Ein/μ.size -Ering*np.sqrt(θ) 913 | 914 | self.steady = {'Ering':Ering, 'Ewg':Ewg, 'Uring': fft.ifft(Ering), 'freq': ν, 'tau': τ} 915 | if not pyType == 'jupyter': 916 | if do_plot: 917 | f, ax = plt.subplots(dpi=120) 918 | ax.plot(1e-12*ν, 30 + 10*np.log10(np.abs(Ewg)**2), label='Waveguide') 919 | ax.plot(1e-12*ν, 30 + 10*np.log10(np.abs(Ering)**2), label='Ring') 920 | ax.legend() 921 | f.show() 922 | return f, ax 923 | 924 | else: 925 | if do_plot: 926 | trace0 = go.Scatter(x = 1e-12*ν,y = 30 + 10*np.log10(np.abs(Ering)**2), 927 | mode = 'lines', name='Res. Power') 928 | trace1 = go.Scatter(x = 1e-12*ν,y = 30 + 10*np.log10(np.abs(Ewg)**2), 929 | mode = 'lines', name='Out Power') 930 | data = [trace1, trace0] 931 | layout = dict(xaxis = dict(title = 'Frequency (THz)'), 932 | yaxis = dict(title = 'Power (dBm)'), 933 | ) 934 | fig = go.Figure(data=data, layout=layout) 935 | iplot(fig) 936 | return fig 937 | 938 | def RetrieveData(self): 939 | ''' 940 | Load the output hdf5 saved by julia and transform it in a user-friendly dictionary to be more pythonistic 941 | ''' 942 | 943 | time.sleep(2) 944 | drct = self.tmp_dir 945 | with h5py.File(self.tmp_dir + 'ResultsJulia.h5', 'r') as S: 946 | if self._debug: 947 | self._logger.info('LLEsovler.RetrieveData','Retrieving results from Julia in {}'.format(self.tmp_dir + 'ResultsJulia.h5')) 948 | self._sol = {} 949 | keys = ['u_probe', 'driving_force'] 950 | for k in keys: 951 | rl = 'Results/{}Real'.format(k) 952 | im = 'Results/{}Imag'.format(k) 953 | self._sol[k] = S[rl][:] + 1j*S[im][:] 954 | 955 | self._sol['detuning'] = S["Results/detuningReal"][:] 956 | self._sol['time'] = S["Results/t_simReal"][:] 957 | self._sol['kappa_ext'] = S["Results/kappa_extReal"][:] 958 | self._sol['kappa0'] = S["Results/kappa_0Real"][:] 959 | 960 | 961 | os.remove(self.tmp_dir + 'ParamLLEJulia.h5') 962 | os.remove(self.tmp_dir + 'ResultsJulia.h5') 963 | 964 | 965 | 966 | # Now Compute the uselfull parameters 967 | # --------------------------------------------- 968 | ind_pump_sweep = self._sim['ind_pump_sweep'] 969 | μcent = -self._sim['mu_sim_center'][0] 970 | # ind_pmp = [self._sim['ind_pmp'][ii] for ii in ind_pump_sweep] 971 | det = 1e-9*self._sol['detuning']/(2*np.pi) 972 | 973 | 974 | L = self._res['R'] 975 | ng = self._res['ng'] 976 | Qc = self._res['Qc'] 977 | Q0 = self._res['Qi'] 978 | tR = L*ng/cts.c 979 | FSR = cts.c/(ng*L) 980 | μlength = self._sim['mu_sim_center'][1]*2+1 981 | 982 | κext = self._sol['kappa_ext'] 983 | κ0 = self._sol['kappa0'] 984 | α = κext+κ0 985 | 986 | u_probe = self._sol['u_probe'] 987 | driving_force = self._sol['driving_force'] 988 | D1 = self._sim['D1_center'] 989 | 990 | ωcenter = self._sim['f_center']*2*np.pi 991 | μcenter = np.linspace(self._sim['mu_sim_center'][0], 992 | self._sim['mu_sim_center'][1], 993 | μlength) 994 | 995 | u_probe = self._sol['u_probe'] 996 | Awg = 1j*np.zeros(u_probe.shape) 997 | Ewg = 1j*np.zeros(u_probe.shape) 998 | Ecav = 1j*np.zeros(u_probe.shape) 999 | Acav = 1j*np.zeros(u_probe.shape) 1000 | Pcomb = np.zeros(u_probe.shape[1]) 1001 | for ii in range(u_probe.shape[1]): 1002 | wg = driving_force[:,ii]*np.sqrt(1-κext) 1003 | cav = np.sqrt(κext)*u_probe[:,ii]*np.exp(1j*np.pi) 1004 | Awg[:, ii] = (wg + cav)/np.sqrt(μlength) 1005 | Acav[:, ii] = np.sqrt(α[0]/2)*u_probe[:,ii]*np.exp(1j*np.pi)/np.sqrt(μlength) 1006 | Ewg[:, ii] = np.fft.fftshift(np.fft.fft(Awg[:, ii]))/np.sqrt(μlength)+1e-12 1007 | Ecav[:, ii] = np.fft.fftshift(np.fft.fft(Acav[:, ii]))/np.sqrt(μlength) 1008 | Pcomb[ii] = np.sum(np.abs(Ecav[:,ii])**2,0) - np.sum([np.abs(Ecav[μcent+jj,ii])**2 for jj in np.unique(self._sim['ind_pmp'])]) 1009 | Pwg = np.sum(np.abs(Awg)**2,0) 1010 | Pcav = np.sum(np.abs(Acav)**2,0) 1011 | 1012 | # -- Comb Frequency -- 1013 | μ = self._sim['mu_sim'] 1014 | μ = np.arange(μ[0], μ[1]+1) 1015 | FSR = self._sim['FSR'] 1016 | self._sol['freq'] = self._sim['f_pmp'][0]+μ*FSR[0] 1017 | 1018 | sol = {'δfreq': self._sol['detuning']/(2*np.pi), 1019 | 'time': self._sol['time'], 1020 | 'Awg': Awg, 1021 | 'Acav': Acav, 1022 | 'Ewg': Ewg, 1023 | 'Ecav': Ecav, 1024 | 'Pcomb': Pcomb, 1025 | 'Pwg': Pwg, 1026 | 'Pcav': Pcav, 1027 | 'μ':μ, 1028 | 'freq': self._sol['freq'] 1029 | } 1030 | 1031 | did_translate = not(self._did_translate) 1032 | if not self._did_translate: 1033 | sol = self._Translator(sol) 1034 | self.sol = _dic2struct(sol, which = 'sol', do_tr = did_translate) 1035 | 1036 | def PlotSpectraMap(self, do_matplotlib = False): 1037 | 1038 | tr = [go.Heatmap(z = 10*np.log10(np.abs(self.sol.Ewg)**2)+30, 1039 | zmax = 0, 1040 | zmin = -90, 1041 | colorbar = dict(title = 'In-wg Power (dBm)'))] 1042 | # tr = [ go.Scatter(y = np.abs(wg)**2)] 1043 | fig = go.FigureWidget(data = tr) 1044 | _ = fig.update_xaxes(title = 'LLE step') 1045 | _ = fig.update_yaxes(title = 'Frequency (THz)') 1046 | # fig.show() 1047 | 1048 | return fig 1049 | 1050 | def PlotTimeMap(self, do_matplotlib = False): 1051 | pass 1052 | 1053 | def PlotCombPower(self, do_matplotlib = False, which = 'all', xaxis = 'steps' ): 1054 | ''' 1055 | 1056 | ''' 1057 | tr = [] 1058 | if xaxis.lower() == 'steps': 1059 | x = np.linspace(0,999,1000) 1060 | xlabel = 'LLE steps' 1061 | elif xaxis.lower() == 'detuning': 1062 | x = 1e-9*self._sol['detuning']/(2*np.pi) 1063 | xlabel = 'Detuning (GHz)' 1064 | 1065 | if not pyType == 'jupyter' or do_matplotlib: 1066 | fig, ax = plt.subplots() 1067 | if which.lower() == 'all': 1068 | ax.plot(x, self.sol.Pcav) 1069 | ax.plot(x, self.sol.Pwg) 1070 | ax.plot(x, self.sol.Pcomb) 1071 | 1072 | if which.lower() == 'comb': 1073 | ax.plot(x, self.sol.Pcomb) 1074 | if which.lower() == 'waveguide': 1075 | ax.plot(x, self.sol.Pwg) 1076 | if which.lower() == 'cavity': 1077 | ax.plot(x, self.sol.Pcav) 1078 | 1079 | ax.legend() 1080 | ax.set_xlabel(xlabel) 1081 | ax.set_ylabel('Power (dBm)') 1082 | 1083 | else: 1084 | if which.lower() == 'all': 1085 | tr += [go.Scatter(x = x, y = self.sol.Pcav, name = 'Pcav')] 1086 | tr += [go.Scatter(x = x, y = self.sol.Pwg, name = 'Pwg')] 1087 | tr += [go.Scatter(x = x, y = self.sol.Pcomb, name = 'Pcomb')] 1088 | 1089 | if which.lower() == 'comb': 1090 | tr += [go.Scatter(x = x, y = self.sol.Pcomb, name = 'Pcomb')] 1091 | if which.lower() == 'waveguide': 1092 | tr += [go.Scatter(x = x, y = self.sol.Pwg, name = 'Pwg')] 1093 | if which.lower() == 'cavity': 1094 | tr += [go.Scatter(x = x, y = self.sol.Pcav, name = 'Pcav')] 1095 | 1096 | 1097 | fig = go.FigureWidget(data = tr) 1098 | _ = fig.update_xaxes(title = xlabel) 1099 | _ = fig.update_yaxes(title = 'Power (W)') 1100 | 1101 | 1102 | return fig 1103 | 1104 | def PlotCombSpectra(self, ind, do_matplotlib = False, plot = True, style = 'comb', xaxis = 'freq', where = 'waveguide', floor = -100): 1105 | # freq = self.sol['freq']*1e-12 1106 | # Sring = 30 + 10*np.log10(np.abs(self.sol['Em_probe'][:, ind])**2) 1107 | # Sout = 30 + 10*np.log10(np.abs(self.sol['Ewg'][:, ind])**2) 1108 | # self.spectra = {'Sout': Sout, 1109 | # 'Sres': Sring, 1110 | # 'freq': freq*1e-12} 1111 | if xaxis.lower() == 'frequencies' or xaxis.lower() == 'freq': 1112 | x = self.sol.freq*1e-12 1113 | xlabel = 'Frequency (THz)' 1114 | elif xaxis.lower() == 'modes': 1115 | x = np.arange(self._sim['mu_sim'][0],self._sim['mu_sim'][-1]) - self._sim['ind_pmp'][0] 1116 | xlabel = 'Mode Numbers' 1117 | 1118 | if where == 'waveguide' or where =='wg': 1119 | y = 10*np.log10(np.abs(self.sol.Ewg[:,ind])**2)+30 1120 | name = ['Waveguide'] 1121 | if where == 'cavity' or where =='cav': 1122 | y = 10*np.log10(np.abs(self.sol.Ecav[:,ind])**2)+30 1123 | name = ['Cavity'] 1124 | if where == 'both': 1125 | y = 10*np.log10(np.abs(self.sol.Ecav[:,ind])**2)+30 1126 | y2 = 10*np.log10(np.abs(self.sol.Ewg[:,ind])**2)+30 1127 | name = ['Cavity', 'Waveguide'] 1128 | 1129 | if style == 'comb': 1130 | x_ = np.zeros(x.size*3) 1131 | x_[::3] = x 1132 | x_[1::3] = x 1133 | x_[2::3] = x 1134 | x = x_ 1135 | 1136 | y_ = np.zeros(y.size*3) 1137 | y_[::3] = floor 1138 | y_[1::3] = y 1139 | y_[2::3] = floor 1140 | y = y_ 1141 | 1142 | if where == 'both': 1143 | y2_ = np.zeros(y2.size*3) 1144 | y2_[::3] = floor 1145 | y2_[1::3] = y2 1146 | y2_[2::3] = floor 1147 | y2 = y2_ 1148 | 1149 | 1150 | if not pyType == 'jupyter' or do_matplotlib: 1151 | fig, ax = plt.subplots() 1152 | ax.plot(x, y, label = name[0]) 1153 | if where == 'both': 1154 | ax.plot(x, y2, label = name[1]) 1155 | ax.set_xlabel(xlabel) 1156 | ax.set_ylabel('Power (dBm)') 1157 | else: 1158 | 1159 | tr = [go.Scatter(x=x, y = y, 1160 | name = name[0])] 1161 | if where == 'both': 1162 | tr += [go.Scatter(x=x, y = y2, 1163 | name = name[1])] 1164 | 1165 | fig = go.FigureWidget(data = tr) 1166 | 1167 | _ = fig.update_xaxes(title = xlabel) 1168 | _ = fig.update_yaxes(title = 'Power (dBm)') 1169 | 1170 | self._plotSpecta = True 1171 | self._indSpectra = ind 1172 | 1173 | 1174 | 1175 | return fig 1176 | 1177 | def PlotSolitonTime(self, ind, f=None, ax=None, label=None, do_matplotlib = False): 1178 | ''' 1179 | Plot the spectra for a given index in the 1000 sub-sampled LLE step 1180 | 1181 | **Input** 1182 | 1183 | - ind : index in the LLE step to plot the spectra 1184 | - f : matplotlib figure handle (if None, new figure) 1185 | - ax : matplotlib axe handle 1186 | - label : label for the legend 1187 | 1188 | **Output** 1189 | 1190 | - τ : Time in the resonator 1191 | - U : Temporal Electric field for the given step of the LLE 1192 | - f : matplotlib figure handle 1193 | - ax : matplotlib axe handle 1194 | ''' 1195 | 1196 | 1197 | tR = 2*np.pi*self._res['R']*self._res['ng']/self._c0 1198 | freq = self.sol['freq'] 1199 | 1200 | τ = np.linspace(-0.5, 0.5, freq.size) * tR 1201 | U = np.abs(self.sol['Acav'][:,ind])**2 1202 | 1203 | self.fasttime ={'U': U, 1204 | 'tau': τ} 1205 | if not pyType == 'jupyter' or do_matplotlib: 1206 | f, ax = plt.subplots(dpi=120) 1207 | ax.plot(τ*1e12 , U/U.max()) 1208 | ax.set_xlabel('Time (ps)') 1209 | ax.set_ylabel('Soliton Energy (a.u)') 1210 | if not pyType == 'jupyter': 1211 | f.show() 1212 | fig = f 1213 | else: 1214 | trace0 = go.Scatter(x = τ*1e12,y = U, 1215 | mode = 'lines') 1216 | data = [trace0] 1217 | layout = dict(xaxis = dict(title = 'Time (ps)'), 1218 | yaxis = dict(title = '|E|^2 (norm)'), 1219 | ) 1220 | fig = go.FigureWidget(data=data, layout=layout) 1221 | 1222 | 1223 | self._plotTime = True 1224 | self._indTime = ind 1225 | return fig 1226 | 1227 | def SaveResults(self, fname, path='./'): 1228 | ''' 1229 | Save the whole class with pickle to be able to easilly call it back or retrieve the results after saving 1230 | 1231 | **Input** 1232 | 1233 | - fname : name to save. The '.pkl' extension will be added 1234 | - path : path to save the results (defaults './') 1235 | ''' 1236 | to_save = copy(self) 1237 | # to_save._sim.pop('domega_disp', None) 1238 | # to_save.sim.pop('domega_disp', None) 1239 | del to_save.JuliaSolver 1240 | fname = path + fname + '.pkl' 1241 | print(fname) 1242 | pkl.dump(to_save, open(fname,'bw')) 1243 | 1244 | def SavePlots2File(self,basename = './', format = 'pdf'): 1245 | if self._plotPower: 1246 | fpwr, axpwr = self.PlotCombPower(do_matplotlib = True) 1247 | Latexify(figname = basename + 'CombPower', fig = fpwr, frmt = format) 1248 | if self._plotSpecta: 1249 | fspec, axspec = self.PlotCombSpectra(self._indSpectra, do_matplotlib = True) 1250 | Latexify(figname = basename + 'CombSpectra', fig = fspec, frmt = format) 1251 | if self._plotTime: 1252 | ftime, axtome = self.PlotSolitonTime(self._indTime, do_matplotlib = True) 1253 | Latexify(figname = basename + 'FastTime', fig = ftime, frmt = format) 1254 | 1255 | def __repr__(self): 1256 | to_print = '' 1257 | to_print = 'Dispersion from: {}\n\n'.format(self._res['dispfile']) 1258 | to_print += 'Resonator Parameters:\n' 1259 | res_table = PrettyTable(['Parameters', 'Value', 'Units']) 1260 | res_table.add_row(['R', "{:.3f}".format(self._res['R']*1e6),'µm']) 1261 | res_table.add_row(['Qi', "{:.3f}".format(self._res['Qi']*1e-6),'x1e6']) 1262 | res_table.add_row(['Qc', "{:.3f}".format(self._res['Qc']*1e-6),'x1e6']) 1263 | if 'gamma' in self._res: 1264 | res_table.add_row(['γ', "{:.3f}".format(self._res['gamma']),'']) 1265 | if 'n2' in self._res: 1266 | res_table.add_row(['n2', "{:.3f}".format(self._res['n2']*1e19),'x1e-19 m2/W']) 1267 | to_print += res_table.get_string() 1268 | to_print += '\n' 1269 | to_print += '\n' 1270 | 1271 | to_print += 'Simulation Parameters:\n' 1272 | sim_table = PrettyTable(['Parameters', 'Value', 'Units']) 1273 | if 'Pin' in self._sim: 1274 | for pp in self._sim['Pin']: 1275 | sim_table.add_row(['Pin',"{:.3f}".format(pp*1e3),'mW']) 1276 | if 'f_pmp' in self._sim: 1277 | for ff in self._sim['f_pmp']: 1278 | sim_table.add_row(['f_pmp',"{:.3f}".format(ff*1e-12),'THz']) 1279 | if 'μ_sim' in self._sim: 1280 | sim_table.add_row(['μ_sim',"{}".format(self._sim['mu_sim']),'']) 1281 | if 'Tscan' in self._sim: 1282 | sim_table.add_row(['Tscan',"{:.3f}".format(self._sim['Tscan']*1e-5),'x1e5 tR']) 1283 | if 'domega_init' in self._sim: 1284 | sim_table.add_row(['δω_init',"{:.3f}".format(self._sim['domega_init']*1e-9),'GHz']) 1285 | if 'domega_end' in self._sim: 1286 | sim_table.add_row(['δω_end',"{:.3f}".format(self._sim['domega_end']*1e-9),'GHz']) 1287 | to_print += sim_table.get_string() 1288 | to_print += '\n' 1289 | 1290 | return to_print 1291 | 1292 | 1293 | 1294 | 1295 | class _dic2struct(): 1296 | def __init__(self, d, which='sim', do_tr=True): 1297 | self._dic = d 1298 | self._which = which 1299 | self._do_tr= do_tr 1300 | self._test = LLEsolver 1301 | for a, b in d.items(): 1302 | setattr(self, a, _dic2struct(b) if isinstance(b, dict) else b) 1303 | 1304 | def reprRes(self): 1305 | greek ={'α': 'alpha', 'β':'beta','γ': 'gamma', 1306 | 'ω': 'omega','δ': 'd', 'Δ': 'D', 'μ': 'mu', 1307 | 'λ': 'lambda','ε': 'epsilon','φ': 'phi'} 1308 | table = PrettyTable(['Parameter', 'Description', 'Values', 'Units']) 1309 | table.add_row(['R', self._dic['R']*1e6, 'Ring radius', 'µm']) 1310 | Qi = self._dic['Qi'] 1311 | exp = np.floor(np.log10(Qi)) 1312 | arg = Qi*10**(-1*exp) 1313 | Qi = '{:.3f} x10^{:.0f}'.format(arg, exp) 1314 | table.add_row(['Qi', Qi, 'Intrinsic quality factor', '']) 1315 | 1316 | Qc = self._dic['Qc'] 1317 | exp = np.floor(np.log10(Qc)) 1318 | arg = Qc*10**(-1*exp) 1319 | Qc = '{:.3f} x10^{:.0f}'.format(arg, exp) 1320 | table.add_row(['Qc', Qc, 'Coupling quality factor', '']) 1321 | try: 1322 | table.add_row(['γ',self._dic['gamma'], 'Non-linear coefficient', 'W^-1 m^-1']) 1323 | except: 1324 | table.add_row(['γ',self._dic['γ'], 'Non-linear coefficient', 'W^-1 m^-1']) 1325 | table.add_row(['dispfile', self._dic['dispfile'], 'mode/resonance frequency file', '']) 1326 | table.vrules = False 1327 | table.header = True 1328 | table.align = "l" 1329 | table.padding_width = 2 1330 | table.padding_height = 25 1331 | 1332 | str_table = table.get_string() 1333 | if self._do_tr: 1334 | for ii in greek.items(): 1335 | str_table = str_table.replace(ii[0], ii[1] ) 1336 | return str_table 1337 | 1338 | def reprSim(self): 1339 | greek ={'α': 'alpha', 'β':'beta','γ': 'gamma', 1340 | 'ω': 'omega','δ': 'd', 'Δ': 'D', 'μ': 'mu', 1341 | 'λ': 'lambda','ε': 'epsilon','φ': 'phi'} 1342 | 1343 | table = PrettyTable(['Parameter', 'Description', 'Values', 'Units']) 1344 | Pin = ['{:.3f}'.format(ii*1e3) for ii in self._dic['Pin']] 1345 | Pin = '[' + ', '.join(Pin) + ']' 1346 | table.add_row(["Pin",Pin + ' (mW)', "Pump power", "W"]) 1347 | table.add_row(["Tscan",self._dic['Tscan'], "Simulation time length", "unit of round trip"]) 1348 | 1349 | f_pmp = ['{:.3f}'.format(ii*1e-12) for ii in self._dic['f_pmp']] 1350 | f_pmp = '[' + ', '.join(f_pmp) + ']' 1351 | table.add_row(["f_pmp",f_pmp + ' (THz)', "Pump frequencies", "Hz"]) 1352 | table.add_row(["φ_pmp",self._dic['phi_pmp'], "Pump phase ", "rad"]) 1353 | 1354 | f_center = '{:.3f}'.format(self._dic['f_center']*1e-12) 1355 | table.add_row(["f_center",f_center + ' (THz)', "Center of the sim domain", "Hz"]) 1356 | 1357 | try: 1358 | δω_init = '{:.3f}'.format(self._dic['δω_init']*1e-9/(2*np.pi)) 1359 | δω_end = '{:.3f}'.format(self._dic['δω_end']*1e-9/(2*np.pi)) 1360 | except: 1361 | δω_init = '{:.3f}'.format(self._dic['domega_init']*1e-9/(2*np.pi)) 1362 | δω_end = '{:.3f}'.format(self._dic['domega_end']*1e-9/(2*np.pi)) 1363 | δω =[] 1364 | try: 1365 | for ii in self._dic['δω']: 1366 | if ii: 1367 | δω += ['{:.3f}'.format(ii*1e-9/(2*np.pi))] 1368 | else: 1369 | δω += ['None'] 1370 | except: 1371 | for ii in self._dic['domega']: 1372 | if ii: 1373 | δω += ['{:.3f}'.format(ii*1e-9/(2*np.pi))] 1374 | else: 1375 | δω += ['None'] 1376 | δω = '[' + ', '.join(δω) + ']' 1377 | table.add_row(["δω_init",δω_init + ' (GHz)', "Start of the frequency sweep", "x2π Hz"]) 1378 | table.add_row(["δω_end",δω_end + ' (GHz)', "End of the frequency sweep", "x2π Hz"]) 1379 | table.add_row(["δω",δω + ' (GHz)', "Fixed detuning", "x2π Hz"]) 1380 | 1381 | 1382 | try: 1383 | table.add_row(["μ_sim",self._dic['μ_sim'], "Simulation mode domain", ""]) 1384 | table.add_row(["μ_fit",self._dic['μ_fit'], "Fit mode domain", ""]) 1385 | table.add_row(["μcenter",self._dic['μcenter'], "Index of the center of the sim domain", ""]) 1386 | except: 1387 | table.add_row(["μ_sim",self._dic['mu_sim'], "Simulation mode domain", ""]) 1388 | table.add_row(["μ_fit",self._dic['mu_fit'], "Fit mode domain", ""]) 1389 | table.add_row(["μcenter",self._dic['mucenter'], "Index of the center of the sim domain", ""]) 1390 | table.add_row(["ind_pmp",self._dic['ind_pmp'], "Pump index relative to center of domain", ""]) 1391 | table.add_row(["ind_pump_sweep",self._dic['ind_pump_sweep'][0], "Pump index to sweep", ""]) 1392 | table.vrules = False 1393 | table.header = True 1394 | table.align = "l" 1395 | table.padding_width = 2 1396 | table.padding_height = 25 1397 | str_table = table.get_string() 1398 | if self._do_tr: 1399 | for ii in greek.items(): 1400 | str_table = str_table.replace(ii[0], ii[1] ) 1401 | return str_table 1402 | 1403 | def reprSol(self): 1404 | greek ={'α': 'alpha', 'β':'beta','γ': 'gamma', 1405 | 'ω': 'omega','δ': 'd', 'Δ': 'D', 'μ': 'mu', 1406 | 'λ': 'lambda','ε': 'epsilon','φ': 'phi'} 1407 | table = PrettyTable(['Parameter', 'Description', 'Values', 'Units']) 1408 | 1409 | try: 1410 | δfreq = '[{:.3f} ... {:.3f}]'.format(self._dic['δfreq'][0]*1e-9, self._dic['δfreq'][-1]*1e-9) 1411 | except: 1412 | δfreq = '[{:.3f} ... {:.3f}]'.format(self._dic['dfreq'][0]*1e-9, self._dic['dfreq'][-1]*1e-9) 1413 | 1414 | table.add_row(["δfreq", δfreq + ' (GHz)', "Pump detuning", "Hz"]) 1415 | 1416 | time = '[{:.3f} ... {:.3f}]'.format(self._dic['time'][0]*1e6, self._dic['time'][-1]*1e6) 1417 | table.add_row(["time", time + ' (μs)', "Simualtion time", "s"]) 1418 | 1419 | N = self._dic['Awg'].shape 1420 | N = '[{} fast time x {} slow time]'.format(N[0], N[1]) 1421 | table.add_row(["Awg", N ,"E. field in time domain in wg,", "V/m"]) 1422 | table.add_row(["Acav", N, "E. field in time domain in cav.", "V/m"]) 1423 | N = self._dic['Ewg'].shape 1424 | N = '[{} spectra x {} slow time]'.format(N[0], N[1]) 1425 | table.add_row(["Ewg",N, "E. field in freq. domain in wg.", "V/m"]) 1426 | table.add_row(["Ecav",N, "E. field in freq. domain in cav.", "V/m"]) 1427 | 1428 | Pcomb = '[{:.3f} ... {:.3f}]'.format(self._dic['Pcomb'][0]*1e3, self._dic['Pcomb'][-1]*1e3) 1429 | table.add_row(["Pcomb", Pcomb + ' (mW)', "Intra-cavity comb power", "W"]) 1430 | 1431 | Pwg = '[{:.3f} ... {:.3f}]'.format(self._dic['Pwg'][0]*1e3, self._dic['Pwg'][-1]*1e3) 1432 | table.add_row(["Pwg", Pwg + ' (mW)', "In-waveguide power", "W"]) 1433 | 1434 | Pcav = '[{:.3f} ... {:.3f}]'.format(self._dic['Pcav'][0]*1e3, self._dic['Pcav'][-1]*1e3) 1435 | table.add_row(["Pcav", Pcav + ' (mW)', "Intracavity power", "W"]) 1436 | 1437 | try: 1438 | μ = '[{:.0f} ... {:.0f}]'.format(self._dic['μ'][0], self._dic['μ'][-1]) 1439 | except: 1440 | μ = '[{:.0f} ... {:.0f}]'.format(self._dic['mu'][0], self._dic['mu'][-1]) 1441 | table.add_row(["μ", μ, "Frequency comb modes index", ""]) 1442 | 1443 | freq = '[{:.3f} ... {:.3f}]'.format(self._dic['freq'][0]*1e-12, self._dic['freq'][-1]*1e-12) 1444 | table.add_row(["freq", freq + ' (THz)', "Frequency comb frequencies", "Hz"]) 1445 | table.vrules = False 1446 | table.header = True 1447 | table.align = "l" 1448 | table.padding_width = 2 1449 | table.padding_height = 25 1450 | str_table = table.get_string() 1451 | if self._do_tr: 1452 | for ii in greek.items(): 1453 | str_table = str_table.replace(ii[0], ii[1] ) 1454 | return str_table 1455 | 1456 | def reprDisp(self): 1457 | greek ={'α': 'alpha', 'β':'beta','γ': 'gamma', 1458 | 'ω': 'omega','δ': 'd', 'Δ': 'D', 'μ': 'mu', 1459 | 'λ': 'lambda','ε': 'epsilon','φ': 'phi'} 1460 | table = PrettyTable(['Parameter', 'Description', 'Values', 'Units']) 1461 | ng = '[{:.3f} ... {:.3f}]'.format(self._dic['ng'][0], self._dic['ng'][-1]) 1462 | table.add_row(['ng', ng, 'Group Index', '']) 1463 | D = '[{:.3f} ... {:.3f}]'.format(self._dic['D'][2], self._dic['D'][-3]) 1464 | table.add_row(['D', D, 'Dispersion', '(ps/nm/km)']) 1465 | 1466 | neff = '[{:.3f} ... {:.3f}]'.format(self._dic['neff'][1], self._dic['neff'][-2]) 1467 | table.add_row(['neff', neff, 'Effctive Index', '']) 1468 | freq = '[{:.3f} ... {:.3f}]'.format(self._dic['freq'][1]*1e-12, self._dic['freq'][-2]*1e-12) 1469 | table.add_row(['freq', freq + ' (THz)', 'Mode frequency', 'Hz']) 1470 | freq_sim = '[{:.3f} ... {:.3f}]'.format(self._dic['freq_sim'][1]*1e-12, self._dic['freq_sim'][-2]*1e-12) 1471 | table.add_row(['freq_sim', freq_sim + ' (THz)', 'Mode frequency to match the sim domain', 'Hz']) 1472 | 1473 | table.add_row(['Dint', '[array for each pump]', 'Integrated Dispersion at the pumps from file', 'Hz']) 1474 | table.add_row(['Dint_sim', '[array for each pump]', 'Integrated Dispersion at the pumps from fit', 'Hz']) 1475 | Dint0 = '[{:.3f} ... {:.3f}]'.format(self._dic['Dint0'][1]*1e-9, self._dic['Dint0'][-2]*1e-9) 1476 | table.add_row(['Dint0', Dint0 + ' (GHz)', 'Dint at the center of sim domain', 'Hz']) 1477 | D1 = f'{self._dic["D1"]*1e-12 :.3f}' 1478 | table.add_row(['D1', D1, 'angular repetition rate', '(x1e12 THz)']) 1479 | FSR = ['{:.3f}'.format(ii*1e-9) for ii in self._dic['FSR']] 1480 | FSR = '[' + ', '.join(FSR)+ ']' 1481 | table.add_row(['FSR', FSR + ' (GHz)', 'Free Spectra Range at the pumps', 'Hz']) 1482 | FSR_center = '{:.3f}'.format(self._dic['FSR_center']*1e-9) 1483 | table.add_row(['FSR_center', FSR_center + ' (GHz)', 'Free Spectra Range at the center of the domain', 'Hz']) 1484 | table.vrules = False 1485 | table.header = True 1486 | table.align = "l" 1487 | table.padding_width = 2 1488 | table.padding_height = 25 1489 | str_table = table.get_string() 1490 | if self._do_tr: 1491 | for ii in greek.items(): 1492 | str_table = str_table.replace(ii[0], ii[1] ) 1493 | return str_table 1494 | 1495 | def __repr__(self): 1496 | if self._which == 'res': 1497 | return self.reprRes() 1498 | elif self._which == 'sim': 1499 | return self.reprSim() 1500 | elif self._which == 'sol': 1501 | return self.reprSol() 1502 | elif self._which == 'disp': 1503 | return self.reprDisp() 1504 | -------------------------------------------------------------------------------- /pypiStuff/dist/pyLLE-4.0.1-py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregmoille/pyLLE/cafb3ccde447a678822ff3545c30c32d09ee7626/pypiStuff/dist/pyLLE-4.0.1-py3-none-any.whl -------------------------------------------------------------------------------- /pypiStuff/dist/pyLLE-4.0.1-py3.9.egg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregmoille/pyLLE/cafb3ccde447a678822ff3545c30c32d09ee7626/pypiStuff/dist/pyLLE-4.0.1-py3.9.egg -------------------------------------------------------------------------------- /pypiStuff/dist/pyLLE-4.0.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregmoille/pyLLE/cafb3ccde447a678822ff3545c30c32d09ee7626/pypiStuff/dist/pyLLE-4.0.1.tar.gz -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | plotly 2 | numpy 3 | scipy 4 | matplotlib 5 | pandas 6 | h5py -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | from setuptools.command.install import install 3 | from setuptools.command.build_py import build_py 4 | import subprocess as sub 5 | import sys 6 | import os 7 | 8 | class MyInstall(install): 9 | def run(self): 10 | install.run(self) 11 | for ii in range(20): 12 | print('-'*10) 13 | if sys.platform == 'darwin': 14 | julia = 'julia' 15 | sub.call([julia, 'InstallPkg.jl']) 16 | if sys.platform == 'linux2': 17 | julia = 'julia' 18 | sub.call([julia, 'InstallPkg.jl']) 19 | if sys.platform == 'win32': 20 | pass 21 | # julia = os.path.expanduser('~') + '\\AppData\\Local\\Julia-1.1.1\\bin\\julia.exe' 22 | 23 | 24 | 25 | setup(name='pyLLE', 26 | version='4.1.2', 27 | description='LLE Solver', 28 | url='https://github.com/gregmoille/pyLLE', 29 | author='Greg Moille', 30 | author_email='gmoille@umed.gov', 31 | license='Open', 32 | long_description='User friendly LLE solver. For more information, visit our github repository page', 33 | packages=['pyLLE'], 34 | install_requires=[ 35 | 'scipy', 36 | 'plotly', 37 | 'numpy', 38 | 'matplotlib', 39 | 'h5py', 40 | 'prettytable', 41 | 'matplotlib', 42 | 'ipdb', 43 | ], 44 | package_data={'': ['*.jl']}, 45 | include_package_data=True, 46 | zip_safe=False, 47 | cmdclass={'install': MyInstall}, 48 | classifiers=( 49 | "Programming Language :: Python :: 3", 50 | "License :: OSI Approved", 51 | "Operating System :: OS Independent", 52 | ),) 53 | --------------------------------------------------------------------------------