Commit 8dc38167 authored by Leon Merten Lohse's avatar Leon Merten Lohse
Browse files

split up fdsolver and propagation. introduce wavelength as parameter

parent b4693942
This diff is collapsed.
This diff is collapsed.
%% Cell type:code id: tags:
``` python
import sys
import numpy as np
import xraylib as xrl
import matplotlib.pyplot as plt
import fresnel.solver as solver
import fresnel.propagate as propagate
```
%% Cell type:code id: tags:
``` python
%matplotlib inline
```
%% Cell type:code id: tags:
``` python
energy = 12. # keV
# geometry
wavelength = 1.2398 / (energy * 1e3) * 1e-3 # mm
nx = 1024
ny = 512
nz = 1000
ztot = 0.4 # mm
wg_radius = 25e-6
xtot = 10 * wg_radius # mm
# units
dx = xtot / nx / wavelength
dz = ztot / nz / wavelength
print(f"dx: {dx}, dz: {dz} wavelengths")
```
%%%% Output: stream
dx: 2.36303234392644, dz: 3871.592192289079 wavelengths
%% Cell type:code id: tags:
``` python
density_Ge = xrl.ElementDensity(xrl.SymbolToAtomicNumber('Ge'))
density_Polyimide = 1.42
density_Si = xrl.ElementDensity(xrl.SymbolToAtomicNumber('Si'))
n_Ge = xrl.Refractive_Index('Ge', energy, density_Ge)
n_Si = xrl.Refractive_Index('Si', energy, density_Si)
n_PI = xrl.Refractive_Index('Kapton Polyimide Film', energy, density_Polyimide)
xx = np.linspace(-xtot/2, xtot/2, nx)
core = (np.abs(xx) < wg_radius)
cladding = ~core
refractive_index = n_Ge * cladding + 1 * core
```
%% Cell type:code id: tags:
``` python
boundary = (0, 0,)
u0 = np.exp(-xx**2 / (2 * (2 * wg_radius)**2)).astype(np.complex128)
```
%% Cell type:code id: tags:
``` python
propagator = solver.PropagatorCS(refractive_index, u0, dz, dx)
propagator = propagate.FDPropagatorCS(refractive_index, u0, dz, dx)
```
%% Cell type:code id: tags:
``` python
field = np.zeros((nz, nx), dtype=np.complex128)
field[0,...] = u0
for iz in range(1, nz):
boundary = (0,0)
field[iz, ...] = propagator.step(refractive_index, boundary)
```
%% Cell type:code id: tags:
``` python
result = field.transpose()
fig, ax = plt.subplots()
im = ax.imshow(np.abs(result[:,:])**2, aspect='auto', clim=(0,3), cmap='jet', extent=[0, ztot, -xtot/2 *1e6, xtot/2 * 1e6])
ax.set_ylim(-2e6 * wg_radius, 2e6 * wg_radius )
fig.colorbar(im)
ax.set_xlabel(r'$z$ (mm)')
ax.set_ylabel(r'$x$ (nm)')
```
%%%% Output: execute_result
Text(0, 0.5, '$x$ (nm)')
%%%% Output: display_data
![](data:image/png;base64,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)
%% Cell type:code id: tags:
``` python
```
......
......@@ -2,8 +2,6 @@ import numpy as np
from . import _solver
_k = 2 * np.pi # all lengths are in units of the wavelength
_compute_potential = lambda n : _k**2 * (1 - n*n)
class Solver2d():
"""
......@@ -186,63 +184,4 @@ class Solver3d():
u_T = _solver.step2d_A0Fs(self.rz, self.rxx, self.ryy, fp.T, self.f.T, up.T, u.T)
self.u = u_T.T
return self.u
class Propagator2d(Solver2d):
def __init__(self, n0, u0, dz, dx):
Az = 2j * _k
Axx = 1
F0 = _compute_potential(n0)
super().__init__(Az, Axx, F0, u0, dz, dx)
def step(self, n, boundary):
F = _compute_potential(n)
return super().step(F, boundary)
class PropagatorCS(Solver2dfull):
def __init__(self, n0, u0, dz, dx):
nx = u0.shape[-1]
self._x = np.linspace(-nx * dx / 2, nx * dx / 2, nx)
Az = 2j * _k * self._x
Axx = self._x
Ax = 1
F0 = _compute_potential(n0)
super().__init__(Az, Axx, Ax, F0, u0, dz, dx)
def step(self, n, boundary):
F = _compute_potential(n) * self._x
return super().step(F, boundary)
class Propagator3d(Solver3d):
def __init__(self, n0, u0, dz, dy, dx):
Az = 2j * _k
Axx = 1
Ayy = 1
F0 = _compute_potential(n0)
super().__init__(Az, Axx, Ayy, F0, u0, dz, dy, dx)
def step(self, n, boundary):
F = _compute_potential(n)
return super().step(F, boundary)
return self.u
\ No newline at end of file
import numpy as np
from pyfftw.interfaces.numpy_fft import fftfreq, ifftshift, fftshift
def fftfreqn(N, d=1.0):
ndim = len(N)
d *= np.ones(ndim)
# index trick: n'th line is a list of ones with a -1 on n'th position
shapes = np.ones((ndim, ndim), dtype='int') - 2 * np.eye(ndim, dtype='int')
xi = [np.reshape(2 * np.pi * fftfreq(N[dim], d[dim]), tuple(shapes[dim, :])) for dim in range(ndim)]
return xi
def crop(a, crop_width):
slices = [slice(w[0], -w[1] if w[1] > 0 else None) for w in crop_width]
return a[tuple(slices)]
from pyfftw.interfaces.numpy_fft import fftn,fftfreq,ifftn,ifftshift,fftshift
from pyfftw.interfaces.numpy_fft import fft,fftn,fftfreq,ifftn,ifftshift,fftshift
import numpy as np
from . import finite_differences as fd
from .misc import fftfreqn, crop
_k = 2 * np.pi # all lengths are in units of the wavelength
_compute_potential = lambda n : _k**2 * (1 - n*n)
_lambda0 = 1. # all lengths are in units of the wavelength
_k0 = 2 * np.pi / _lambda0
_compute_potential = lambda n_, k_=_k0 : k_*k_ * (1 - n_*n_)
def fftfreqn(N):
ndim = len(N)
# index trick: n'th line is a list of ones with a -1 on n'th position
shapes = np.ones((ndim, ndim), dtype='int') - 2 * np.eye(ndim, dtype='int')
def fresnelKernel(shape, fresnelNumbers, method='TF'):
xi = [np.reshape(2 * np.pi * fftfreq(N[dim]), tuple(shapes[dim, :])) for dim in range(ndim)]
return xi
def crop(a, crop_width):
slices = [slice(w[0], -w[1] if w[1] > 0 else None) for w in crop_width]
return a[tuple(slices)]
def fresnelKernel(N, fresnelNumbers):
ndim = len(N)
ndim = len(shape)
if np.isscalar(fresnelNumbers):
fresnelNumbers = fresnelNumbers * np.ones(ndim)
kernel = np.ones(N, dtype=np.complex128)
xi = fftfreqn(N)
kernel = np.ones(shape, dtype=np.complex128)
if method is 'TF':
# transfer function (TF) method
xi = fftfreqn(shape, 1)
for dim in range(ndim):
kernel *= np.exp((-1j/(2*_k0*fresnelNumbers[dim])) * xi[dim]**2)
for dim in range(ndim):
kernel *= np.exp((-1j/(2*_k*fresnelNumbers[dim])) * xi[dim]**2)
return kernel
return kernel
if method is 'IR':
# impulse response (IR) method
# phase factor
kernel *= np.prod(np.sqrt(abs(fresnelNumbers))) * np.exp((-1j*np.pi/4) * np.sign(fresnelNumbers))
# TODO: use dedicated function for this to avoid loss of precision
x = fftfreqn(shape, 1/shape)
for dim in range(ndim):
kernel *= fft(np.exp(1j*np.pi*fresnelNumbers[dim] * x[dim]**2))
return kernel
raise ValueError(f'Invalid method "{method}". Must be "TF" or "IR".')
class FresnelPropagator2d():
class FresnelPropagator():
"""
Multi-Slice approximation
Paganin, Coherent X-Ray Optics, p101
"""
dtype = np.complex128
def __init__(self, u0, d, wl=1., method='TF'):
ndim = len(d)
# TODO: check input
# assert u0 is array
# assert d is tuple
# assert wl is scalar numeric
# assert ndim == u0.ndim + 1
def __init__(self, u0, dz, dx):
self._dz = d[0]
self._dperp = np.array(d[1:])
self._ones = np.ones(u0.shape, dtype = self.dtype)
self._k = _k0 / wl
self._nx = u0.shape[-1]
self._ones = np.ones((self._nx,), dtype = self.dtype)
self._dz = dz
fresnelNumber = dx**2 / dz # in units of wavelength
self._fourierKernel = fresnelKernel(self._ones.shape, fresnelNumber)
fresnelNumbers = self._dperp**2 / (self._dz * wl)
self._fourierKernel = fresnelKernel(self._ones.shape, fresnelNumbers, method)
self.u = ifftshift(u0)
def step(self, n):
F = _compute_potential(ifftshift(n)) * self._ones
nshift = ifftshift(n)
self._realKernel = np.exp(-1j / (2 * _k) * self._dz * F )
F = _compute_potential(nshift, self._k) * self._ones
self._realKernel = np.exp(-1j / (2 * self._k) * self._dz * F )
up = self.u
self.u = ifftn(self._fourierKernel * fftn(self._realKernel * up))
......@@ -69,38 +88,71 @@ class FresnelPropagator2d():
return fftshift(self.u)
class FresnelPropagator3d():
"""
Multi-Slice approximation
Paganin, Coherent X-Ray Optics, p101
"""
dtype = np.complex128
class FDPropagator2d(fd.Solver2d):
def __init__(self, u0, dz, dy, dx):
def __init__(self, n0, u0, dz, dx, wl=1.):
self._nx = u0.shape[-1]
self._nx = u0.shape[-2]
self._ones = np.ones((self._ny, self._nx,), dtype = self.dtype)
self._k = _k0 / wl
self._dz = dz
fresnelNumber = dx**2 / dz # in units of wavelength
self._fourierKernel = fresnelKernel(self._ones.shape, fresnelNumber)
self.u = ifftshift(u0)
Az = 2j * self._k
Axx = 1
F0 = _compute_potential(n0, self._k)
super().__init__(Az, Axx, F0, u0, dz, dx)
def step(self, n, boundary):
F = _compute_potential(n, self._k)
return super().step(F, boundary)
class FDPropagatorCS(fd.Solver2dfull):
def __init__(self, n0, u0, dz, dx, wl=1.):
nx = u0.shape[-1]
self._x = np.linspace(-nx * dx / 2, nx * dx / 2, nx)
def step(self, n):
F = _compute_potential(ifftshift(n)) * self._ones
self._realKernel = np.exp(-1j / (2 * _k) * self._dz * F )
up = self.u
self.u = ifftn(self._fourierKernel * fftn(self._realKernel * up))
self._k = _k0 / wl
Az = 2j * self._k * self._x
Axx = self._x
Ax = 1
F0 = _compute_potential(n0, self._k) * self._x
super().__init__(Az, Axx, Ax, F0, u0, dz, dx)
def step(self, n, boundary):
F = _compute_potential(n, self._k) * self._x
return super().step(F, boundary)
class FDPropagator3d(fd.Solver3d):
def __init__(self, n0, u0, dz, dy, dx, wl=1.):
self._k = _k0 / wl
Az = 2j * self._k
Axx = 1
Ayy = 1
F0 = _compute_potential(n0, self._k)
super().__init__(Az, Axx, Ayy, F0, u0, dz, dy, dx)
return fftshift(self.u)
def step(self, n, boundary):
F = _compute_potential(n, self._k)
return super().step(F, boundary)
def fresnelPropagate(im, fresnelNumbers, sizePad=None, sizeOut=None, padMode='edge'):
......
......@@ -2,7 +2,7 @@
#include <complex>
#include <Eigen/Dense>
#include <iostream>
//#include <iostream>
namespace algebra{
......@@ -174,7 +174,7 @@ namespace finite_differences{
size_t nx = u.rows() - 2;
size_t ny = u.cols() - 2;
std::cout << "nx " << u.cols() << ", ny " << u.rows() << std::endl;
// std::cout << "nx " << u.cols() << ", ny " << u.rows() << std::endl;
// first halfstep
// x at i + 1/2
......@@ -264,7 +264,7 @@ namespace finite_differences{
size_t nx = u.rows() - 2;
size_t ny = u.cols() - 2;
std::cout << "nx " << u.cols() << ", ny " << u.rows() << std::endl;
// std::cout << "nx " << u.cols() << ", ny " << u.rows() << std::endl;
// first halfstep
// x at i + 1/2
......
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