From 0313d3b4adabd81188d3ed7b050b8b7aec0d0c8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ne=C4=8Dada?= Date: Thu, 23 Jun 2022 09:07:10 +0300 Subject: [PATCH] vswf set specification support for "single particle type" scripts --- misc/finiterectlat-constant-driving.py | 8 ++++---- misc/finiterectlat-modes.py | 8 ++++---- misc/finiterectlat-scatter.py | 8 ++++---- misc/rectlat_simple_modes.py | 8 ++++---- qpms/argproc.py | 18 ++++++++++++++++++ 5 files changed, 34 insertions(+), 16 deletions(-) diff --git a/misc/finiterectlat-constant-driving.py b/misc/finiterectlat-constant-driving.py index a46861a..06c70be 100755 --- a/misc/finiterectlat-constant-driving.py +++ b/misc/finiterectlat-constant-driving.py @@ -4,7 +4,7 @@ import math from qpms.argproc import ArgParser, make_dict_action, sslice, annotate_pdf_metadata 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("--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)') @@ -36,8 +36,8 @@ px, py = a.period 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) -defaultprefix = "cd_%s_p%gnmx%gnm_%dx%d_m%s_n%s_k_%g_%g_f%geV_L%d_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) +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, ap.bspecstr, "SO3" if a.symmetry_adapted is None else a.symmetry_adapted) logging.info("Default file prefix: %s" % defaultprefix) import numpy as np @@ -126,7 +126,7 @@ orig_xy = np.stack(np.meshgrid(orig_x, orig_y), axis = -1) omega = ap.omega -bspec = BaseSpec(lMax = a.lMax) +bspec = ap.bspec medium = EpsMuGenerator(ap.background_epsmu) particles= [Particle(orig_xy[i], ap.tmgen, bspec) for i in np.ndindex(orig_xy.shape[:-1])] diff --git a/misc/finiterectlat-modes.py b/misc/finiterectlat-modes.py index 701d61d..1d6461f 100755 --- a/misc/finiterectlat-modes.py +++ b/misc/finiterectlat-modes.py @@ -4,7 +4,7 @@ import math 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("-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)) 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" % ( - particlestr, px*1e9, py*1e9, Nx, Ny, str(a.material), str(a.background), a.lMax, +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), ap.bspecstr, str(a.centre), a.ar, a.ai, a.N, 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) -bspec = BaseSpec(lMax = a.lMax) +bspec = ap.bspec medium = EpsMuGenerator(ap.background_epsmu) particles= [Particle(orig_xy[i], ap.tmgen, bspec) for i in np.ndindex(orig_xy.shape[:-1])] diff --git a/misc/finiterectlat-scatter.py b/misc/finiterectlat-scatter.py index 82eae39..2e8c481 100755 --- a/misc/finiterectlat-scatter.py +++ b/misc/finiterectlat-scatter.py @@ -5,7 +5,7 @@ pi = math.pi 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", "--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") @@ -36,8 +36,8 @@ px, py = a.period 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) -defaultprefix = "%s_p%gnmx%gnm_%dx%d_m%s_bg%s_φ%gπ_θ(%g_%g)π_ψ%gπ_χ%gπ_f%s_L%d" % ( - 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, ) +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, ap.bspecstr, ) 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) -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])] sym = FinitePointGroup(point_group_info['D2h']) diff --git a/misc/rectlat_simple_modes.py b/misc/rectlat_simple_modes.py index b39b5e4..13b3083 100755 --- a/misc/rectlat_simple_modes.py +++ b/misc/rectlat_simple_modes.py @@ -3,7 +3,7 @@ import math 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("--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) @@ -28,8 +28,8 @@ if a.kpi: 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) -defaultprefix = "%s_p%gnmx%gnm_m%s_n%g_b%+d_k(%g_%g)um-1_L%d_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) +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, ap.bspecstr, a.N) import logging 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 -bspec = BaseSpec(lMax = a.lMax) +bspec = ap.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) diff --git a/qpms/argproc.py b/qpms/argproc.py index bdbffb2..afc93a8 100644 --- a/qpms/argproc.py +++ b/qpms/argproc.py @@ -323,6 +323,12 @@ class ArgParser: action=make_dict_action(argtype=hashable_complex_matrix, postaction='store', first_is_key=True), 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 = { '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')), @@ -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_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_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'), '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)"), @@ -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',), ()), '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_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',), ()), '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',), ()), @@ -501,6 +509,16 @@ class ArgParser: from .constants import 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 import numpy as np from .constants import eV, hbar