4 from qpms
.argproc
import ArgParser
, sfloat
, annotate_pdf_metadata
6 ap
= ArgParser(['background', 'lattice2d', 'multi_particle', 'omega_seq'])
8 ap
.add_argument("-k", nargs
=2, type=sfloat
, required
=True, help='k vector', metavar
=('K_X', 'K_Y'))
9 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)")
11 ap
.add_argument("-g", "--little-group", type=str, default
="trivial_g", help="Little group for subspace irrep classification", action
="store")
13 ap
.add_argument("-o", "--output", type=str, required
=False, help='output path (if not provided, will be generated automatically)')
14 ap
.add_argument("-O", "--plot-out", type=str, required
=False, help="path to plot output (optional)")
15 ap
.add_argument("-P", "--plot", action
='store_true', help="if -p not given, plot to a default path")
16 ap
.add_argument("-s", "--singular_values", type=int, default
=10, help="Number of singular values to plot")
21 logging
.basicConfig(format
='%(asctime)s %(message)s', level
=logging
.INFO
)
24 #Important! The particles are supposed to be of D2h/D4h symmetry
25 # thegroup = 'D4h' if px == py and not a.D2 else 'D2h'
27 a1
= ap
.direct_basis
[0]
28 a2
= ap
.direct_basis
[1]
30 particlestr
= "svdinterval" # TODO particle string specifier or some hash, do this in argproc.py
31 defaultprefix
= "%s_basis%gnm_%gnm__%gnm_%gnm_f(%g..%g..%g)eV_k%g_%g" % (
32 particlestr
, a1
[0]*1e9
, a1
[1]*1e9
, a2
[0]*1e9
, a2
[1]*1e9
, *(a
.eV_seq
), ap
.k
[0], ap
.k
[1])
33 logging
.info("Default file prefix: %s" % defaultprefix
)
39 from qpms
.cybspec
import BaseSpec
40 from qpms
.cytmatrices
import CTMatrix
, TMatrixGenerator
41 from qpms
.qpms_c
import Particle
, pgsl_ignore_error
, empty_lattice_modes_xy
42 from qpms
.cymaterials
import EpsMu
, EpsMuGenerator
, LorentzDrudeModel
, lorentz_drude
43 from qpms
.cycommon
import DebugFlags
, dbgmsg_enable
44 from qpms
import FinitePointGroup
, ScatteringSystem
, BesselType
, eV
, hbar
45 from qpms
.symmetries
import point_group_info
49 irrep_labels
= {"B2''":"$B_2''$",
60 dbgmsg_enable(DebugFlags
.INTEGRATION
)
66 logging
.info("%d frequencies from %g to %g eV" % (len(omegas
), omegas
[0]/eh
, omegas
[-1]/eh
))
68 particles
= ap
.get_particles()
70 ss
, ssw
= ScatteringSystem
.create(particles
, ap
.background_emg
, omegas
[0], latticebasis
=ap
.direct_basis
)
71 k
= np
.array([ap
.k
[0], ap
.k
[1], 0])
72 # Auxillary finite scattering system for irrep decomposition, quite a hack
73 ss1
, ssw1
= ScatteringSystem
.create(particles
, ap
.background_emg
, omegas
[0],sym
=FinitePointGroup(point_group_info
[ap
.little_group
]))
75 wavenumbers
= np
.empty(omegas
.shape
)
76 SVs
= [None] * ss1
.nirreps
77 for iri
in range(ss1
.nirreps
):
78 SVs
[iri
] = np
.empty(omegas
.shape
+(ss1
.saecv_sizes
[iri
],))
79 for i
, omega
in enumerate(omegas
):
81 wavenumbers
[i
] = ssw
.wavenumber
.real
82 if ssw
.wavenumber
.imag
:
83 warnings
.warn("Non-zero imaginary wavenumber encountered")
84 with
pgsl_ignore_error(15): # avoid gsl crashing on underflow; maybe not needed
85 ImTW
= ssw
.modeproblem_matrix_full(k
)
86 for iri
in range(ss1
.nirreps
):
87 ImTW_packed
= ss1
.pack_matrix(ImTW
, iri
)
88 SVs
[iri
][i
] = np
.linalg
.svd(ImTW_packed
, compute_uv
= False)
90 outfile
= defaultprefix
+ ".npz" if a
.output
is None else a
.output
91 np
.savez(outfile
, meta
={**vars(a
), 'qpms_version' : qpms
.__version
__()}, omegas
=omegas
, wavenumbers
=wavenumbers
, SVs
=np
.concatenate(SVs
, axis
=-1), irrep_names
=ss1
.irrep_names
, irrep_sizes
=ss1
.saecv_sizes
, unitcell_area
=ss
.unitcell_volume
93 logging
.info("Saved to %s" % outfile
)
96 if a
.plot
or (a
.plot_out
is not None):
99 from matplotlib
import pyplot
as plt
100 from matplotlib
.backends
.backend_pdf
import PdfPages
103 ax
= fig
.add_subplot(111)
104 cc
= plt
.rcParams
['axes.prop_cycle']()
105 for iri
in range(ss1
.nirreps
):
107 nlines
= min(a
.singular_values
, ss1
.saecv_sizes
[iri
])
108 for i
in range(nlines
):
109 ax
.plot(omegas
/eh
, SVs
[iri
][:,-1-i
],
110 label
= None if i
else irrep_labels
.get(ss1
.irrep_names
[iri
], ss1
.irrep_names
[iri
]),
113 if hasattr(ap
, "background_epsmu"):
115 omegas_empty
= empty_lattice_modes_xy(ap
.background_epsmu
, ap
.reciprocal_basis2pi
, k
, omegas
[-1])
116 for om
in omegas_empty
:
117 if om
/eh
> xlim
[0] and om
/eh
< xlim
[1]:
118 ax
.axvline(om
/eh
, ls
=':')
119 ax
.set_xlabel('$\hbar \omega / \mathrm{eV}$')
120 ax
.set_ylabel('Singular values')
123 plotfile
= defaultprefix
+ ".pdf" if a
.plot_out
is None else a
.plot_out
124 with
PdfPages(plotfile
) as pdf
:
126 annotate_pdf_metadata(pdf
, scriptname
='lat2d_realfreqsvd.py')