2019-11-14 17:23:19 +02:00
#!/usr/bin/env python3
import math
2019-12-13 00:11:40 +02:00
from qpms . argproc import ArgParser
2019-11-14 17:23:19 +02:00
2019-12-13 00:11:40 +02:00
2019-12-14 13:26:40 +02:00
ap = ArgParser ( [ ' rectlattice2d_finite ' , ' single_particle ' , ' single_lMax ' , ' single_omega ' ] )
2019-11-14 17:23:19 +02:00
ap . add_argument ( " -k " , ' --kx-lim ' , nargs = 2 , type = float , required = True , help = ' k vector ' , metavar = ( ' KX_MIN ' , ' KX_MAX ' ) )
# ap.add_argument("--kpi", action='store_true', help="Indicates that the k vector is given in natural units instead of SI, i.e. the arguments given by -k shall be automatically multiplied by pi / period (given by -p argument)")
ap . add_argument ( " -o " , " --output " , type = str , required = False , help = ' output path (if not provided, will be generated automatically) ' )
ap . add_argument ( " -N " , type = int , default = " 151 " , help = " Number of angles " )
ap . add_argument ( " -O " , " --plot-out " , type = str , required = False , help = " path to plot output (optional) " )
ap . add_argument ( " -P " , " --plot " , action = ' store_true ' , help = " if -p not given, plot to a default path " )
2019-12-13 00:11:40 +02:00
ap . add_argument ( " -g " , " --save-gradually " , action = ' store_true ' , help = " saves the partial result after computing each irrep " )
2019-11-14 17:23:19 +02:00
a = ap . parse_args ( )
2019-12-13 00:11:40 +02:00
import logging
logging . basicConfig ( format = ' %(asctime)s %(message)s ' , level = logging . INFO )
2019-12-14 13:26:40 +02:00
Nx , Ny = a . size
px , py = a . period
2019-11-14 17:23:19 +02:00
particlestr = ( " sph " if a . height is None else " cyl " ) + ( " _r %g nm " % ( a . radius * 1e9 ) )
2019-12-13 00:11:40 +02:00
if a . height is not None : particlestr + = " _h %g nm " % ( a . height * 1e9 )
2019-12-14 13:26:40 +02:00
defaultprefix = " %s _p %g nmx %g nm_ %d x %d _m %s _n %g _angles( %g _ %g )_Ey_f %g eV_L %d _cn %d " % (
particlestr , px * 1e9 , py * 1e9 , Nx , Ny , str ( a . material ) , a . refractive_index , a . kx_lim [ 0 ] , a . kx_lim [ 1 ] , a . eV , a . lMax , a . N )
logging . info ( " Default file prefix: %s " % defaultprefix )
2019-11-14 17:23:19 +02:00
import numpy as np
import qpms
from qpms . cybspec import BaseSpec
from qpms . cytmatrices import CTMatrix , TMatrixGenerator
from qpms . qpms_c import Particle
from qpms . cymaterials import EpsMu , EpsMuGenerator , LorentzDrudeModel , lorentz_drude
from qpms . cycommon import DebugFlags , dbgmsg_enable
from qpms import FinitePointGroup , ScatteringSystem , BesselType , eV , hbar
from qpms . symmetries import point_group_info
eh = eV / hbar
dbgmsg_enable ( DebugFlags . INTEGRATION )
#Particle positions
2019-12-14 13:26:40 +02:00
orig_x = ( np . arange ( Nx / 2 ) + ( 0 if ( Nx % 2 ) else .5 ) ) * px
orig_y = ( np . arange ( Ny / 2 ) + ( 0 if ( Ny % 2 ) else .5 ) ) * py
2019-11-14 17:23:19 +02:00
orig_xy = np . stack ( np . meshgrid ( orig_x , orig_y ) , axis = - 1 )
2019-12-13 00:11:40 +02:00
omega = ap . omega
2019-11-14 17:23:19 +02:00
bspec = BaseSpec ( lMax = a . lMax )
2019-12-13 00:11:40 +02:00
Tmatrix = ap . tmgen ( bspec , ap . omega )
2019-11-14 17:23:19 +02:00
particles = [ Particle ( orig_xy [ i ] , Tmatrix ) for i in np . ndindex ( orig_xy . shape [ : - 1 ] ) ]
sym = FinitePointGroup ( point_group_info [ ' D2h ' ] )
ss = ScatteringSystem ( particles , sym )
2019-12-13 00:11:40 +02:00
wavenumber = ap . background_epsmu . k ( omega ) . real # Currently, ScatteringSystem does not "remember" frequency nor wavenumber
2019-11-14 17:23:19 +02:00
sinalpha_list = np . linspace ( a . kx_lim [ 0 ] , a . kx_lim [ 1 ] , a . N )
# Plane wave data
E_cart_list = np . empty ( ( a . N , 3 ) , dtype = complex )
E_cart_list [ : , : ] = np . array ( ( 0 , 1 , 0 ) ) [ None , : ]
k_cart_list = np . empty ( ( a . N , 3 ) , dtype = float )
k_cart_list [ : , 0 ] = sinalpha_list
k_cart_list [ : , 1 ] = 0
k_cart_list [ : , 2 ] = np . sqrt ( 1 - sinalpha_list * * 2 )
k_cart_list * = wavenumber
σ _ext_list_ir = np . empty ( ( a . N , ss . nirreps ) , dtype = float )
σ _scat_list_ir = np . empty ( ( a . N , ss . nirreps ) , dtype = float )
2019-12-13 00:11:40 +02:00
outfile_tmp = defaultprefix + " .tmp " if a . output is None else a . output + " .tmp "
2019-11-14 17:23:19 +02:00
for iri in range ( ss . nirreps ) :
2019-12-13 00:11:40 +02:00
logging . info ( " processing irrep %d / %d " % ( iri , ss . nirreps ) )
LU = None # to trigger garbage collection before the next call
translation_matrix = None
2019-11-14 17:23:19 +02:00
LU = ss . scatter_solver ( wavenumber , iri )
2019-12-13 00:11:40 +02:00
logging . info ( " LU solver created " )
2019-11-14 17:23:19 +02:00
translation_matrix = ss . translation_matrix_packed ( wavenumber , iri , BesselType . REGULAR ) + np . eye ( ss . saecv_sizes [ iri ] )
2019-12-13 00:11:40 +02:00
logging . info ( " auxillary translation matrix created " )
2019-11-14 17:23:19 +02:00
for j in range ( a . N ) :
# the following two could be calculated only once, but probably not a big deal
ã = ss . planewave_full ( k_cart = k_cart_list [ j ] , E_cart = E_cart_list [ j ] )
Tã = ss . apply_Tmatrices_full ( ã )
Tãi = ss . pack_vector ( Tã , iri )
ãi = ss . pack_vector ( ã , iri )
fi = LU ( Tãi )
σ _ext_list_ir[ j , iri ] = - np . vdot ( ãi , fi ) . real / wavenumber * * 2
σ _scat_list_ir[ j , iri ] = np . vdot ( fi , np . dot ( translation_matrix , fi ) ) . real / wavenumber * * 2
2019-12-13 00:11:40 +02:00
if a . save_gradually :
iriout = outfile_tmp + " . %d " % iri
np . savez ( iriout , iri = iri , meta = vars ( a ) , sinalpha = sinalpha_list , k_cart = k_cart_list , E_cart = E_cart_list ,
omega = omega , wavenumber = wavenumber , σ _ext_list_ir= σ _ext_list_ir[ : , iri ] , σ _scat_list_ir= σ _scat_list_ir[ : , iri ] )
logging . info ( " partial results saved to %s " % iriout )
2019-11-14 17:23:19 +02:00
σ _abs_list_ir = σ _ext_list_ir - σ _scat_list_ir
σ _abs= np . sum ( σ _abs_list_ir, axis = - 1 )
σ _scat= np . sum ( σ _scat_list_ir, axis = - 1 )
σ _ext= np . sum ( σ _ext_list_ir, axis = - 1 )
outfile = defaultprefix + " .npz " if a . output is None else a . output
2019-12-13 00:11:40 +02:00
np . savez ( outfile , meta = vars ( a ) , sinalpha = sinalpha_list , k_cart = k_cart_list , E_cart = E_cart_list , σ _ext= σ _ext, σ _abs= σ _abs, σ _scat= σ _scat,
2019-11-14 17:23:19 +02:00
σ _ext_ir= σ _ext_list_ir, σ _abs_ir= σ _abs_list_ir, σ _scat_ir= σ _scat_list_ir, omega = omega , wavenumber = wavenumber
)
2019-12-13 00:11:40 +02:00
logging . info ( " Saved to %s " % outfile )
2019-11-14 17:23:19 +02:00
if a . plot or ( a . plot_out is not None ) :
2019-12-13 00:11:40 +02:00
import matplotlib
matplotlib . use ( ' pdf ' )
2019-11-14 17:23:19 +02:00
from matplotlib import pyplot as plt
2019-12-13 00:11:40 +02:00
2019-11-14 17:23:19 +02:00
fig = plt . figure ( )
ax = fig . add_subplot ( 111 )
ax . plot ( sinalpha_list , σ _ext* 1e12 , label = ' $ \ sigma_ \ mathrm {ext} $ ' )
ax . plot ( sinalpha_list , σ _scat* 1e12 , label = ' $ \ sigma_ \ mathrm {scat} $ ' )
ax . plot ( sinalpha_list , σ _abs* 1e12 , label = ' $ \ sigma_ \ mathrm {abs} $ ' )
ax . legend ( )
ax . set_xlabel ( ' $ \ sin \\ alpha$ ' )
ax . set_ylabel ( ' $ \ sigma/ \ mathrm { \ mu m^2}$ ' )
plotfile = defaultprefix + " .pdf " if a . plot_out is None else a . plot_out
fig . savefig ( plotfile )
exit ( 0 )