vswf set specification support for "single particle type" scripts

This commit is contained in:
Marek Nečada 2022-06-23 09:07:10 +03:00
parent cfd25c6218
commit 0313d3b4ad
5 changed files with 34 additions and 16 deletions

View File

@ -4,7 +4,7 @@ import math
from qpms.argproc import ArgParser, make_dict_action, sslice, annotate_pdf_metadata from qpms.argproc import ArgParser, make_dict_action, sslice, annotate_pdf_metadata
figscale=3 figscale=3
ap = ArgParser(['rectlattice2d_finite', 'single_particle', 'single_lMax', 'single_omega']) ap = ArgParser(['rectlattice2d_finite', 'single_particle', 'single_lMax_or_vswfset', 'single_omega'])
ap.add_argument("-k", '--wavevector', nargs=2, type=float, required=True, help='"Bloch" vector, modulating phase of the driving', metavar=('KX', 'KY'), default=(0., 0.)) ap.add_argument("-k", '--wavevector', nargs=2, type=float, required=True, help='"Bloch" vector, modulating phase of the driving', metavar=('KX', 'KY'), default=(0., 0.))
# 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("--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("-o", "--output", type=str, required=False, help='output path (if not provided, will be generated automatically)')
@ -36,8 +36,8 @@ px, py = a.period
particlestr = ("sph" if a.height is None else "cyl") + ("_r%gnm" % (a.radius*1e9)) particlestr = ("sph" if a.height is None else "cyl") + ("_r%gnm" % (a.radius*1e9))
if a.height is not None: particlestr += "_h%gnm" % (a.height * 1e9) if a.height is not None: particlestr += "_h%gnm" % (a.height * 1e9)
defaultprefix = "cd_%s_p%gnmx%gnm_%dx%d_m%s_n%s_k_%g_%g_f%geV_L%d_micro-%s" % ( defaultprefix = "cd_%s_p%gnmx%gnm_%dx%d_m%s_n%s_k_%g_%g_f%geV_%s_micro-%s" % (
particlestr, px*1e9, py*1e9, Nx, Ny, str(a.material), str(a.background), a.wavevector[0], a.wavevector[1], a.eV, a.lMax, "SO3" if a.symmetry_adapted is None else a.symmetry_adapted) particlestr, px*1e9, py*1e9, Nx, Ny, str(a.material), str(a.background), a.wavevector[0], a.wavevector[1], a.eV, ap.bspecstr, "SO3" if a.symmetry_adapted is None else a.symmetry_adapted)
logging.info("Default file prefix: %s" % defaultprefix) logging.info("Default file prefix: %s" % defaultprefix)
import numpy as np import numpy as np
@ -126,7 +126,7 @@ orig_xy = np.stack(np.meshgrid(orig_x, orig_y), axis = -1)
omega = ap.omega omega = ap.omega
bspec = BaseSpec(lMax = a.lMax) bspec = ap.bspec
medium = EpsMuGenerator(ap.background_epsmu) medium = EpsMuGenerator(ap.background_epsmu)
particles= [Particle(orig_xy[i], ap.tmgen, bspec) for i in np.ndindex(orig_xy.shape[:-1])] particles= [Particle(orig_xy[i], ap.tmgen, bspec) for i in np.ndindex(orig_xy.shape[:-1])]

View File

@ -4,7 +4,7 @@ import math
from qpms.argproc import ArgParser, annotate_pdf_metadata from qpms.argproc import ArgParser, annotate_pdf_metadata
ap = ArgParser(['rectlattice2d_finite', 'background_analytical', 'single_particle', 'single_lMax', ]) ap = ArgParser(['rectlattice2d_finite', 'background_analytical', 'single_particle', 'single_lMax_or_vswfset', ])
ap.add_argument("-t", "--rank-tolerance", type=float, default=1e11) ap.add_argument("-t", "--rank-tolerance", type=float, default=1e11)
ap.add_argument("-c", "--min-candidates", type=int, default=1, help='always try at least this many eigenvalue candidates, even if their SVs in the rank tests are lower than rank_tolerance') ap.add_argument("-c", "--min-candidates", type=int, default=1, help='always try at least this many eigenvalue candidates, even if their SVs in the rank tests are lower than rank_tolerance')
@ -35,8 +35,8 @@ thegroup = 'D4h' if px == py and Nx == Ny and not a.D2 else 'D2h'
particlestr = ("sph" if a.height is None else "cyl") + ("_r%gnm" % (a.radius*1e9)) particlestr = ("sph" if a.height is None else "cyl") + ("_r%gnm" % (a.radius*1e9))
if a.height is not None: particlestr += "_h%gnm" % (a.height * 1e9) if a.height is not None: particlestr += "_h%gnm" % (a.height * 1e9)
defaultprefix = "%s_p%gnmx%gnm_%dx%d_m%s_B%s_L%d_c(%s±%g±%gj)eV_cn%d_%s" % ( defaultprefix = "%s_p%gnmx%gnm_%dx%d_m%s_B%s_%s_c(%s±%g±%gj)eV_cn%d_%s" % (
particlestr, px*1e9, py*1e9, Nx, Ny, str(a.material), str(a.background), a.lMax, particlestr, px*1e9, py*1e9, Nx, Ny, str(a.material), str(a.background), ap.bspecstr,
str(a.centre), a.ar, a.ai, a.N, str(a.centre), a.ar, a.ai, a.N,
thegroup, thegroup,
) )
@ -70,7 +70,7 @@ orig_y = (np.arange(Ny/2) + (0 if (Ny % 2) else .5)) * py
orig_xy = np.stack(np.meshgrid(orig_x, orig_y), axis = -1) orig_xy = np.stack(np.meshgrid(orig_x, orig_y), axis = -1)
bspec = BaseSpec(lMax = a.lMax) bspec = ap.bspec
medium = EpsMuGenerator(ap.background_epsmu) medium = EpsMuGenerator(ap.background_epsmu)
particles= [Particle(orig_xy[i], ap.tmgen, bspec) for i in np.ndindex(orig_xy.shape[:-1])] particles= [Particle(orig_xy[i], ap.tmgen, bspec) for i in np.ndindex(orig_xy.shape[:-1])]

View File

@ -5,7 +5,7 @@ pi = math.pi
from qpms.argproc import ArgParser from qpms.argproc import ArgParser
ap = ArgParser(['rectlattice2d_finite', 'single_particle', 'single_lMax', 'omega_seq_real_ng', 'planewave']) ap = ArgParser(['rectlattice2d_finite', 'single_particle', 'single_lMax_or_vswfset', 'omega_seq_real_ng', 'planewave'])
ap.add_argument("-o", "--output", type=str, required=False, help='output path (if not provided, will be generated automatically)') ap.add_argument("-o", "--output", type=str, required=False, help='output path (if not provided, will be generated automatically)')
ap.add_argument("-O", "--plot-out", type=str, required=False, help="path to plot output (optional)") 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") ap.add_argument("-P", "--plot", action='store_true', help="if -p not given, plot to a default path")
@ -36,8 +36,8 @@ px, py = a.period
particlestr = ("sph" if a.height is None else "cyl") + ("_r%gnm" % (a.radius*1e9)) particlestr = ("sph" if a.height is None else "cyl") + ("_r%gnm" % (a.radius*1e9))
if a.height is not None: particlestr += "_h%gnm" % (a.height * 1e9) if a.height is not None: particlestr += "_h%gnm" % (a.height * 1e9)
defaultprefix = "%s_p%gnmx%gnm_%dx%d_m%s_bg%s%gπ_θ(%g_%g)π_ψ%gπ_χ%gπ_f%s_L%d" % ( defaultprefix = "%s_p%gnmx%gnm_%dx%d_m%s_bg%s%gπ_θ(%g_%g)π_ψ%gπ_χ%gπ_f%s_%s" % (
particlestr, px*1e9, py*1e9, Nx, Ny, str(a.material), str(a.background), a.phi/pi, np.amin(a.theta)/pi, np.amax(a.theta)/pi, a.psi/pi, a.chi/pi, ap.omega_descr, a.lMax, ) particlestr, px*1e9, py*1e9, Nx, Ny, str(a.material), str(a.background), a.phi/pi, np.amin(a.theta)/pi, np.amax(a.theta)/pi, a.psi/pi, a.chi/pi, ap.omega_descr, ap.bspecstr, )
logging.info("Default file prefix: %s" % defaultprefix) logging.info("Default file prefix: %s" % defaultprefix)
@ -47,7 +47,7 @@ orig_y = (np.arange(Ny/2) + (0 if (Ny % 2) else .5)) * py
orig_xy = np.stack(np.meshgrid(orig_x, orig_y), axis = -1) orig_xy = np.stack(np.meshgrid(orig_x, orig_y), axis = -1)
bspec = BaseSpec(lMax = a.lMax) bspec = ap.bspec
particles= [Particle(orig_xy[i], ap.tmgen, bspec=bspec) for i in np.ndindex(orig_xy.shape[:-1])] particles= [Particle(orig_xy[i], ap.tmgen, bspec=bspec) for i in np.ndindex(orig_xy.shape[:-1])]
sym = FinitePointGroup(point_group_info['D2h']) sym = FinitePointGroup(point_group_info['D2h'])

View File

@ -3,7 +3,7 @@
import math import math
from qpms.argproc import ArgParser, annotate_pdf_metadata from qpms.argproc import ArgParser, annotate_pdf_metadata
ap = ArgParser(['rectlattice2d', 'const_real_background', 'single_particle', 'single_lMax']) # const_real_background needed for calculation of the diffracted orders ap = ArgParser(['rectlattice2d', 'const_real_background', 'single_particle', 'single_lMax_or_vswfset']) # const_real_background needed for calculation of the diffracted orders
ap.add_argument("-k", nargs=2, type=float, required=True, help='k vector', metavar=('K_X', 'K_Y')) ap.add_argument("-k", nargs=2, type=float, required=True, help='k vector', metavar=('K_X', 'K_Y'))
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("--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("--rank-tol", type=float, required=False) ap.add_argument("--rank-tol", type=float, required=False)
@ -28,8 +28,8 @@ if a.kpi:
particlestr = ("sph" if a.height is None else "cyl") + ("_r%gnm" % (a.radius*1e9)) particlestr = ("sph" if a.height is None else "cyl") + ("_r%gnm" % (a.radius*1e9))
if a.height is not None: particlestr += "_h%gnm" % (a.height * 1e9) if a.height is not None: particlestr += "_h%gnm" % (a.height * 1e9)
defaultprefix = "%s_p%gnmx%gnm_m%s_n%g_b%+d_k(%g_%g)um-1_L%d_cn%d" % ( defaultprefix = "%s_p%gnmx%gnm_m%s_n%g_b%+d_k(%g_%g)um-1_%s_cn%d" % (
particlestr, px*1e9, py*1e9, str(a.material), a.refractive_index, a.band_index, a.k[0]*1e-6, a.k[1]*1e-6, a.lMax, a.N) particlestr, px*1e9, py*1e9, str(a.material), a.refractive_index, a.band_index, a.k[0]*1e-6, a.k[1]*1e-6, ap.bspecstr, a.N)
import logging import logging
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO) logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
@ -91,7 +91,7 @@ freqradius = .5 * (top - bottom) * a.interval_factor
centfreq = bottom + freqradius if a.band_index > 0 else top - freqradius centfreq = bottom + freqradius if a.band_index > 0 else top - freqradius
bspec = BaseSpec(lMax = a.lMax) bspec = ap.bspec
pp = Particle(orig_xy[0][0], t = ap.tmgen, bspec=bspec) pp = Particle(orig_xy[0][0], t = ap.tmgen, bspec=bspec)
ss, ssw = ScatteringSystem.create([pp], ap.background_emg, centfreq, latticebasis = ap.direct_basis) ss, ssw = ScatteringSystem.create([pp], ap.background_emg, centfreq, latticebasis = ap.direct_basis)

View File

@ -323,6 +323,12 @@ class ArgParser:
action=make_dict_action(argtype=hashable_complex_matrix, postaction='store', first_is_key=True), action=make_dict_action(argtype=hashable_complex_matrix, postaction='store', first_is_key=True),
help='constant T-matrix (elements must correspond to ++vswf-set)') help='constant T-matrix (elements must correspond to ++vswf-set)')
def __add_single_lMax_or_vswfset_group(ap):
grp = ap.add_mutually_exclusive_group(required=True)
grp.add_argument("-w", "--vswf-set", type=string2bspec_tuple,
help='Manual specification of VSWF set codes (format as a python list of integers); see docs on qpms_uvswfi_t for valid codes or simply use --lMax instead. Overrides --lMax.')
grp.add_argument("-L", "--lMax", type=int, default=3, help='multipole degree cutoff')
atomic_arguments = { atomic_arguments = {
'rectlattice2d_periods': lambda ap: ap.add_argument("-p", "--period", type=float, nargs='+', required=True, help='square/rectangular lattice periods', metavar=('px','[py]')), 'rectlattice2d_periods': lambda ap: ap.add_argument("-p", "--period", type=float, nargs='+', required=True, help='square/rectangular lattice periods', metavar=('px','[py]')),
'rectlattice2d_counts': lambda ap: ap.add_argument("--size", type=int, nargs=2, required=True, help='rectangular array size (particle column, row count)', metavar=('NCOLS', 'NROWS')), 'rectlattice2d_counts': lambda ap: ap.add_argument("--size", type=int, nargs=2, required=True, help='rectangular array size (particle column, row count)', metavar=('NCOLS', 'NROWS')),
@ -338,6 +344,7 @@ class ArgParser:
'bg_real_refractive_index': lambda ap: ap.add_argument("-n", "--refractive-index", type=float, default=1., help='background medium strictly real refractive index'), 'bg_real_refractive_index': lambda ap: ap.add_argument("-n", "--refractive-index", type=float, default=1., help='background medium strictly real refractive index'),
'bg_analytical': lambda ap: ap.add_argument("-B", "--background", type=material_spec, default=1., help="Background medium specification (constant real or complex refractive index, or supported material label)"), 'bg_analytical': lambda ap: ap.add_argument("-B", "--background", type=material_spec, default=1., help="Background medium specification (constant real or complex refractive index, or supported material label)"),
'single_lMax': lambda ap: ap.add_argument("-L", "--lMax", type=int, required=True, default=3, help='multipole degree cutoff'), 'single_lMax': lambda ap: ap.add_argument("-L", "--lMax", type=int, required=True, default=3, help='multipole degree cutoff'),
'single_lMax_or_vswfset': __add_single_lMax_or_vswfset_group,
'single_lMax_extend': lambda ap: ap.add_argument("--lMax-extend", type=int, required=False, default=6, help='multipole degree cutoff for T-matrix calculation (cylindrical particles only'), 'single_lMax_extend': lambda ap: ap.add_argument("--lMax-extend", type=int, required=False, default=6, help='multipole degree cutoff for T-matrix calculation (cylindrical particles only'),
'outfile': lambda ap: ap.add_argument("-o", "--output", type=str, required=False, help='output path (if not provided, will be generated automatically)'), # TODO consider type=argparse.FileType('w') 'outfile': lambda ap: ap.add_argument("-o", "--output", type=str, required=False, help='output path (if not provided, will be generated automatically)'), # TODO consider type=argparse.FileType('w')
'plot_out': lambda ap: ap.add_argument("-O", "--plot-out", type=str, required=False, help="path to plot output (optional)"), 'plot_out': lambda ap: ap.add_argument("-O", "--plot-out", type=str, required=False, help="path to plot output (optional)"),
@ -354,6 +361,7 @@ class ArgParser:
'single_particle': ("Single particle definition (shape [currently spherical or cylindrical]) and materials, incl. background)", ('background',), ('single_material', 'single_radius', 'single_height', 'single_lMax_extend'), ('_eval_single_tmgen',), ()), 'single_particle': ("Single particle definition (shape [currently spherical or cylindrical]) and materials, incl. background)", ('background',), ('single_material', 'single_radius', 'single_height', 'single_lMax_extend'), ('_eval_single_tmgen',), ()),
'multi_particle': ("One or more particle definition (shape [curently spherical or cylindrical]), materials, and positions)", ('background',), ('multi_particle',), ('_process_multi_particle',), ()), 'multi_particle': ("One or more particle definition (shape [curently spherical or cylindrical]), materials, and positions)", ('background',), ('multi_particle',), ('_process_multi_particle',), ()),
'single_lMax': ("Single particle lMax definition", (), ('single_lMax',), (), ()), 'single_lMax': ("Single particle lMax definition", (), ('single_lMax',), (), ()),
'single_lMax_or_vswfset': ("Single particle lMax definition", (), ('single_lMax_or_vswfset',), ('_eval_single_lMax_or_vswfset',), ()),
'single_omega': ("Single angular frequency", (), ('single_frequency_eV',), ('_eval_single_omega',), ()), 'single_omega': ("Single angular frequency", (), ('single_frequency_eV',), ('_eval_single_omega',), ()),
'omega_seq': ("Equidistant real frequency range with possibility of adding individual frequencies", (), ('seq_frequency_eV', 'multiple_frequency_eV_optional',), ('_eval_omega_seq',), ()), 'omega_seq': ("Equidistant real frequency range with possibility of adding individual frequencies", (), ('seq_frequency_eV', 'multiple_frequency_eV_optional',), ('_eval_omega_seq',), ()),
'omega_seq_real_ng': ("Equidistant real frequency ranges or individual frequencies (new syntax)", (), ('real_frequencies_eV_ng',), ('_eval_omega_seq_real_ng',), ()), 'omega_seq_real_ng': ("Equidistant real frequency ranges or individual frequencies (new syntax)", (), ('real_frequencies_eV_ng',), ('_eval_omega_seq_real_ng',), ()),
@ -501,6 +509,16 @@ class ArgParser:
from .constants import eV, hbar from .constants import eV, hbar
self.omega = self.args.eV * eV / hbar self.omega = self.args.eV * eV / hbar
def _eval_single_lMax_or_vswfset(self): #feature: single_lMax_or_vswfset
from .cybspec import BaseSpec
a = self.args
if a.vswf_set is not None:
self.bspec = BaseSpec(a.vswf_set)
self.bspecstr = "WF%s" % (str(a.vswf_set),)
else:
self.bspec = BaseSpec(lMax=a.lMax)
self.bspecstr = "L%d" % (a.lMax,)
def _eval_omega_seq(self): # feature: omega_seq def _eval_omega_seq(self): # feature: omega_seq
import numpy as np import numpy as np
from .constants import eV, hbar from .constants import eV, hbar