Commit 2bbbda1d authored by Antoine RAVETTA's avatar Antoine RAVETTA

verify Marburger's law

parent fda2201b
"""
# Non linear terms
Compute $\mathcal{E} \mapsto f(\mathcal{E})$ to add non linear terms. Test one after another, with divergence if only Kerr effect.
Add non linear integrations in a symmetric manner:
* Fourth $z$ step and half $t$ step with half non linear terms;
* Half $z$ step and total $r$ step;
* Fourth $z$ step and half $t$ step with half non linear terms.
**Warning**: do not forget $\Delta z/4$, $\Delta z/2$ and $\Delta t/2$ factors to obtain the right scale.
"""
import numpy as np
import scipy.sparse
import scipy.linalg as la
import matplotlib.pyplot as plt
class CrankNicolsonFocus:
"""A class that solves dE/dz = D1*d2E/dr2 + V(r)*dE/dr + D2*d2E/dt2 + f(E)"""
# Cylindrical grid with rectangular time
def set_grid(self, r_max, n_r, z_min, z_max, n_z, t_min, t_max, n_t):
self.r_max, self.n_r = r_max, n_r
self.z_min, self.z_max, self.n_z = z_min, z_max, n_z
self.t_min, self.t_max, self.n_t = t_min, t_max, n_t
self.r_pts, self.delta_r = np.linspace(0, r_max, n_r, retstep=True, endpoint=False, dtype=complex)
self.z_pts, self.delta_z = np.linspace(z_min, z_max, n_z, retstep=True, endpoint=False, dtype=complex)
self.t_pts, self.delta_t = np.linspace(t_min, t_max, n_t, retstep=True, endpoint=False, dtype=complex)
# Parameters of the scheme
# Dr for diffraction, Dt for dispersion
def set_parameters(self, Dr, Dt, V, f):
# V has to be vectorised
self.Dr, self.Dt, self.V, self.f = Dr, Dt, V, f
# One solving step for r dependency and t dependency
def solve(self, E_init):
# Coefficient of matrices
sig_r = self.Dr * (self.delta_z) / 2. / self.delta_r**2
sig_t = self.Dt * (self.delta_z/2) / 2. / (self.delta_t)**2 # (half t operator)
nu = lambda x : -self.V(x) * (self.delta_z) / 4. / self.delta_r # minus sign for V convention
# Empty solution matrix (z,r,t)
self.E_matrix = np.zeros([self.n_z, self.n_r, self.n_t], dtype=complex)
# Sparse solver
Ar = self._fillAr_sp(sig_r, nu, self.n_r)
Br = self._fillBr_sp(sig_r, nu, self.n_r)
At = self._fillAt_sp(sig_t, self.n_t) # null advection coefficient
Bt = self._fillBt_sp(sig_t, self.n_t) # null advection coefficient
# Set boundary conditions
# Spatial:
# Dirichlet at infinity
Ar[1,-1] = 1.0
Ar[2,-2] = 0.0
Br[-1,-1] = 0.0
Br[-1,-2] = 0.0
# Neumann at r=0
Ar[0,1] = -2*sig_r
Br[0,1] = 2*sig_r
# Time
# Neumann at t=t_min, t_max
for b in [0,1]:
At[1,-b] = 1.0
At[2*b,1-3*b] = 0.0
Bt[-b,-b] = 0.0
Bt[-b,1-3*b] = 0.0
# Propagate
E = E_init.copy()
E1 = E_init.copy()
E2 = E_init.copy()
for n in range(self.n_z):
# General step initialisation
self.E_matrix[n,:,:] = E
# First fourth step
# t solver for each r with half non linear
fE1 = self.f(E)
#print('fE1 :', fE1)
#print('max fE1 :', np.amax(fE1))
# Non linear term at origin
if n==0:
fE_old = fE1.copy()
# Half non linear term with half sum
for i in range(self.n_r):
E1[i,:] = la.solve_banded((1,1), At, Bt.dot(E[i,:]) + \
(self.delta_z/2.) * (1.5 * fE1[i,:] - 0.5 * fE_old[i,:]), \
check_finite=False)
# Non linear term update
fE_old = fE1.copy()
# Middle half step
# r solver solver for each t
for i in range(self.n_t):
E2[:,i] = la.solve_banded((1,1), Ar, Br.dot(E1[:,i]), \
check_finite=False)
# Second fourth step
# t solver for each r with half non linear
fE2 = self.f(E2)
#print('fE2 :', fE2)
#print('max fE2 :', np.amax(fE2))
# Half non linear term with half sum (old already defined even at n=0)
for i in range(self.n_r):
E[i,:] = la.solve_banded((1,1), At, Bt.dot(E2[i,:]) + \
(self.delta_z/2.) * (1.5 * fE2[i,:] - 0.5 * fE_old[i,:]), \
check_finite=False)
# Non linear term update
fE_old = fE2.copy()
# E has been updated, put into E_matrix at next step
# Deep copy of results for export
# np.savetxt ?
def get_E(self):
return self.E_matrix.copy()
# Diagonal packing for banded r
def _fillAr_sp(self, sig, nu, n):
"""Returns a tridiagonal matrix in compact form ab[1+i-j,j]=a[i,j]"""
A = np.zeros([3,n], dtype=complex) # A has three diagonals and size n
# Superdiagonal
A[0,1:] = -(sig - nu(self.r_pts[:-1]))
# Diagonal
A[1] = 1+2*sig
# Subdiagonal
A[2,:-1] = -(sig + nu(self.r_pts[1:]))
return A
# Diagonal packing for banded t
def _fillAt_sp(self, sig, n):
"""Returns a tridiagonal matrix in compact form ab[1+i-j,j]=a[i,j]"""
_o = np.ones(n, dtype=complex)
A = np.zeros([3,n], dtype=complex) # A has three diagonals and size n
# Superdiagonal
A[0,1:] = -sig
# Diagonal
A[1] = 1+2*sig
# Subdiagonal
A[2,:-1] = -sig
return A
# Sparse tridiagonal storage for r
def _fillBr_sp(self, sig, nu, n):
"""Returns a tridiagonal sparse matrix in csr-form"""
_o = np.ones(n, dtype=complex)
supdiag = (sig - nu(self.r_pts[:-1]))
diag = (1-2*sig)*_o
subdiag = (sig + nu(self.r_pts[1:]))
return scipy.sparse.diags([supdiag, diag, subdiag], [1,0,-1], (n,n), format="csr")
# Sparse tridiagonal storage for t
def _fillBt_sp(self, sig, n):
"""Returns a tridiagonal sparse matrix in csr-form"""
_o = np.ones(n, dtype=complex)
supdiag = sig*_o[:-1]
diag = (1-2*sig)*_o
subdiag = sig*_o[:-1]
return scipy.sparse.diags([supdiag, diag, subdiag], [1,0,-1], (n,n), format="csr")
\ No newline at end of file
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"diff : 5.570423008216336e-08j\n",
"disp : -1e-28j\n"
]
}
],
"source": [
"import numpy as np\n",
"from KCN import CrankNicolsonFocus\n",
"\n",
"lambd = 0.7e-6\n",
"\n",
"k = 2 * np.pi / lambd\n",
"k_2 = 2e-28\n",
"\n",
"w0 = 1e-3\n",
"tp = 85e-15\n",
"#tp = 1\n",
"\n",
"diff_coeff = 1j*1/(2 * k)\n",
"#diff_coeff = 0\n",
"#diff_coeff = 1e-4\n",
"disp_coeff = -1j*k_2/2\n",
"#disp_coeff = 1j * 1e-25\n",
"#disp_coeff = 0\n",
"\n",
"print('diff :', diff_coeff)\n",
"print('disp :', disp_coeff)\n",
"\n",
"\n",
"def potential(r):\n",
" try:\n",
" return diff_coeff / r\n",
" except ZeroDivisionError:\n",
" return 0\n",
"\n",
"\n",
"def gaussian(r, t, r0=0, w0=1, t0=0, tp=1, Pin=1):\n",
" return np.sqrt(2*Pin/(np.pi*w0**2)) * np.exp(-(r-r0)** 2/(w0**2) - (t-t0)** 2/(tp**2))\n",
"\n",
"\n",
"def initial_enveloppe(r_pts, t_pts, w0, tp, Pin):\n",
" return np.array([[gaussian(r_pts[i], t_pts[j], w0=w0, tp=tp, Pin=Pin) for j in range(len(t_pts))] \\\n",
" for i in range(len(r_pts))])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Kerr effect"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"#----- Non linearities --------------\n",
"\n",
"n2 = 5.57e-23\n",
"\n",
"def kerr(E):\n",
" return 1j * k * n2 * np.abs(E)**2 * E"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Marburger's law\n",
"\n",
"We test different initial power and look if the z value at which the beam collapses\n",
"correspond to the law"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Critical Power"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1.1795895759768706\n",
"4.487989505128277\n"
]
}
],
"source": [
"Pc = 3.37 * np.pi / 2 / k ** 2 / n2\n",
"print(Pc * 1e-9)\n",
"\n",
"zR = k * w0 ** 2 / 2\n",
"print(zR)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Instanciation"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Pin_list = [i*1e9 for i in range(1,11)]\n",
"E_list = []\n",
"zc_list = []"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for Pin in Pin_list:\n",
" crank = CrankNicolsonFocus()\n",
"\n",
" crank.set_grid(r_max=2.8e-3, n_r=100, z_min=0, z_max=2, n_z=300, t_min=-5e-13, t_max=5e-13, n_t=100)\n",
" crank.set_parameters(Dr=diff_coeff, Dt=disp_coeff, V=potential, f=kerr)\n",
"\n",
" crank.solve(initial_enveloppe(crank.r_pts, crank.t_pts, w0, tp, Pin))\n",
" E_list.append(crank.get_E())"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for E in E_list:\n",
" E = np.nan_to_num(E)\n",
" max_ind = np.unravel_index(np.argmax(E, axis=None), E.shape)\n",
" zc = max_ind[0] * crank.delta_z\n",
" zc_list.append(zc)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
......@@ -247,7 +247,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Non linear terms"
"# Non linear terms"
]
},
{
......@@ -266,7 +266,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
......@@ -453,7 +453,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 7,
"metadata": {},
"outputs": [
{
......@@ -505,7 +505,7 @@
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": 8,
"metadata": {},
"outputs": [
{
......@@ -536,7 +536,7 @@
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
......@@ -545,7 +545,7 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 10,
"metadata": {
"scrolled": true
},
......@@ -593,7 +593,7 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
......@@ -602,7 +602,7 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": 12,
"metadata": {},
"outputs": [
{
......@@ -627,7 +627,7 @@
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": 13,
"metadata": {},
"outputs": [
{
......@@ -652,7 +652,7 @@
},
{
"cell_type": "code",
"execution_count": 21,
"execution_count": 14,
"metadata": {
"scrolled": true
},
......@@ -688,7 +688,7 @@
},
{
"cell_type": "code",
"execution_count": 22,
"execution_count": 15,
"metadata": {},
"outputs": [
{
......@@ -731,25 +731,10 @@
},
{
"cell_type": "code",
"execution_count": 23,
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"def potential(r):\n",
" try:\n",
" return diff_coeff / r\n",
" except ZeroDivisionError:\n",
" return 0\n",
"\n",
"\n",
"def gaussian(r, t, r0=0, w0=1, t0=0, tp=1, Pin=1):\n",
" return np.sqrt(2*Pin/(np.pi*w0**2)) * np.exp(-(r-r0)** 2/(w0**2) - (t-t0)** 2/(tp**2))\n",
"\n",
"\n",
"def initial_enveloppe(r_pts, t_pts, w0, tp, Pin):\n",
" return np.array([[gaussian(r_pts[i], t_pts[j], w0=w0, tp=tp, Pin=Pin) for j in range(len(t_pts))] \\\n",
" for i in range(len(r_pts))])\n",
"\n",
"#----- Non linearities --------------\n",
"\n",
"def kerr(E):\n",
......@@ -758,7 +743,7 @@
},
{
"cell_type": "code",
"execution_count": 30,
"execution_count": 17,
"metadata": {},
"outputs": [
{
......@@ -797,19 +782,18 @@
},
{
"cell_type": "code",
"execution_count": 128,
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/antoine/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:3: RuntimeWarning: divide by zero encountered in true_divide\n",
" This is separate from the ipykernel package so we can avoid doing imports until\n",
"/home/antoine/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:3: RuntimeWarning: invalid value encountered in true_divide\n",
" This is separate from the ipykernel package so we can avoid doing imports until\n",
"/home/antoine/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:24: RuntimeWarning: divide by zero encountered in true_divide\n",
"/home/antoine/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:24: RuntimeWarning: invalid value encountered in true_divide\n",
"/home/antoine/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:36: RuntimeWarning: invalid value encountered in multiply\n",
"/home/antoine/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:19: RuntimeWarning: overflow encountered in multiply\n",
"/home/antoine/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:4: RuntimeWarning: overflow encountered in multiply\n",
" after removing the cwd from sys.path.\n",
"/home/antoine/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:87: RuntimeWarning: invalid value encountered in multiply\n",
"/home/antoine/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:107: RuntimeWarning: invalid value encountered in multiply\n"
]
......@@ -826,7 +810,7 @@
},
{
"cell_type": "code",
"execution_count": 129,
"execution_count": 19,
"metadata": {},
"outputs": [
{
......@@ -860,27 +844,35 @@
"fig.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We transform all the NaNs into zeros"
]
},
{
"cell_type": "code",
"execution_count": 130,
"execution_count": 50,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2.8e-05\n"
"(223, 0, 50)\n"
]
}
],
"source": [
"E = crank.get_E()\n",
"print(crank.delta_r)"
"F = np.nan_to_num(E)\n",
"print(np.unravel_index(np.argmax(F, axis=None), F.shape))"
]
},
{
"cell_type": "code",
"execution_count": 131,
"execution_count": 51,
"metadata": {},
"outputs": [
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment