Compare commits
144 Commits
Author | SHA1 | Date |
---|---|---|
Marek Nečada | 33d144cf68 | |
Marek Nečada | 53764f3dd1 | |
Marek Nečada | f9620e1d11 | |
Marek Nečada | 5e4f9130fb | |
Marek Nečada | 03e5be17f9 | |
Marek Nečada | 74ce35605b | |
Marek Nečada | 2a85b16347 | |
Marek Nečada | ac0d322246 | |
Marek Nečada | a1472f3db6 | |
Marek Nečada | 260b053102 | |
Marek Nečada | 78992188fd | |
Marek Nečada | e7f7cd38d2 | |
Marek Nečada | b525c66043 | |
Marek Nečada | e69b927ec3 | |
Marek Nečada | 2731a87ef7 | |
Marek Nečada | 3a34effe34 | |
Marek Nečada | 1aac5de903 | |
Marek Nečada | 87c2fd24fe | |
Marek Nečada | aea0afee15 | |
Kristian Arjas | 77a3566aba | |
Kristian Arjas | 24a6ea01d7 | |
Kristian Arjas | 50a5aa11a6 | |
Marek Nečada | 572e15edbb | |
Marek Nečada | b12fc991e5 | |
Marek Nečada | a5b137847a | |
Marek Nečada | 314cde1b99 | |
Marek Nečada | 80ee8b0d53 | |
Marek Nečada | 087cd1cab3 | |
Marek Nečada | 9d556e7b23 | |
Marek Nečada | f19c590d6e | |
Marek Nečada | 2be3521333 | |
Marek Nečada | 64f77557a7 | |
Marek Nečada | 7e0d7639e8 | |
Marek Nečada | 36c5d5236a | |
Marek Nečada | cf2aca7f03 | |
Marek Nečada | 3479721455 | |
Marek Nečada | 6189918348 | |
Marek Nečada | 031397aacd | |
Marek Nečada | 1a4b279eff | |
Marek Nečada | 5285210489 | |
Marek Nečada | ae62cf903d | |
Marek Nečada | 5246229b2d | |
Marek Nečada | 868e603f1c | |
Marek Nečada | bf297c11c3 | |
Marek Nečada | 9e42520371 | |
Marek Nečada | a68e1d8f8c | |
Kristian Arjas | a669e661e3 | |
Kristian Arjas | d19a7813f7 | |
Marek Nečada | 07c2f678b2 | |
Marek Nečada | 38fca209ef | |
Marek Nečada | 24b5371e18 | |
Marek Nečada | 840744ec97 | |
Marek Nečada | 38a4dbfcd7 | |
Marek Nečada | 17824b062e | |
Marek Nečada | 1328077490 | |
Marek Nečada | f7883a713b | |
Marek Nečada | 93118cfc07 | |
Marek Nečada | fc27320988 | |
Marek Nečada | 676240cf0d | |
Marek Nečada | 7d92f4990b | |
Marek Nečada | e0861a7d40 | |
Marek Nečada | 87c2b08701 | |
Marek Nečada | 6c79a9116b | |
Marek Nečada | 884baca199 | |
Marek Nečada | e0e572db3c | |
Marek Nečada | 42497939c1 | |
Marek Nečada | cc8d2644bf | |
Marek Nečada | 14e415dfc5 | |
Marek Nečada | 7f2e36e956 | |
Marek Nečada | eba5784042 | |
Marek Nečada | b09dfc8784 | |
Marek Nečada | 62ba67ebcf | |
Marek Nečada | a0b0d72686 | |
Marek Nečada | 299bb6fc03 | |
Marek Nečada | cae5cee97d | |
Marek Nečada | 827499c3ff | |
Marek Nečada | 0c442ba745 | |
Marek Nečada | a34f3b37d9 | |
Marek Nečada | fec399d16b | |
Marek Nečada | e2584e3163 | |
Marek Nečada | 582f33bb00 | |
Marek Nečada | ecf599bb15 | |
Marek Nečada | d3cd9b9350 | |
Marek Nečada | 90458af3be | |
Marek Nečada | 6009de6fa2 | |
Marek Nečada | 3046f03734 | |
Marek Nečada | 61a2baecb0 | |
Marek Nečada | 97977dbb46 | |
Marek Nečada | 975d23b557 | |
Marek Nečada | c50f40a747 | |
Marek Nečada | c056099d5a | |
Marek Nečada | 93cde82a9a | |
Marek Nečada | 626ffd77cd | |
Marek Nečada | 85dbf79caa | |
Marek Nečada | 932f30e9f9 | |
Marek Nečada | 43c2de4f35 | |
Steven G. Johnson | 206f8b65a1 | |
Marek Nečada | a7c95d0ee0 | |
Marek Nečada | 4bf3bb1bb1 | |
Marek Nečada | 1221012c7b | |
Marek Nečada | 80efed00fd | |
Marek Nečada | 2f14de7dde | |
Marek Nečada | 14a5c32202 | |
Marek Nečada | 999dc7f72e | |
Marek Nečada | 8ed4bdb683 | |
Marek Nečada | 83e76b1f95 | |
Marek Nečada | 69fd19c019 | |
Marek Nečada | 2460f3b644 | |
Marek Nečada | fe55f4b391 | |
Marek Nečada | 74f6c489ba | |
Marek Nečada | 3da6e5cfb2 | |
Marek Nečada | c5c148ca40 | |
Marek Nečada | 63aa338891 | |
Marek Nečada | 2ccf9e2c5d | |
Marek Nečada | dd2391abf7 | |
Marek Nečada | 231a76529d | |
Marek Nečada | ba06abe13f | |
Marek Nečada | 3458acca16 | |
Marek Nečada | 3f266f5501 | |
Marek Nečada | 9b9338be05 | |
Marek Nečada | e774b30d0c | |
Marek Nečada | 70d03f75aa | |
Marek Nečada | dc503158bf | |
Marek Nečada | a88694e7ef | |
Marek Nečada | 8b7e2c6332 | |
Marek Nečada | 858e7d0697 | |
Marek Nečada | a14d0e5bc4 | |
Marek Nečada | ac6e94065a | |
Marek Nečada | 5f729d28a7 | |
Marek Nečada | 1b4b397093 | |
Marek Nečada | 20a13cdb2c | |
Marek Nečada | 3ebc1af946 | |
Marek Nečada | 2798fcce49 | |
Marek Nečada | c031d65905 | |
Marek Nečada | 3c7377e5fe | |
Marek Nečada | b3d15a1bb7 | |
Marek Nečada | aa82b3a01a | |
Marek Nečada | 35ffc61faf | |
Marek Nečada | b00a6db4cf | |
Marek Nečada | 301a0e0633 | |
Marek Nečada | 433be52bbc | |
Marek Nečada | 4b2e48f459 | |
Marek Nečada | 9bf2f6a57a | |
Marek Nečada | 15328a3dc9 |
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: buildqpms-alpine-preinstlibs
|
||||
|
||||
workspace:
|
||||
path: /home/qpmsbuild/qpms
|
||||
|
||||
# don't run in master until the python/lapacke linking problem is resolved
|
||||
trigger:
|
||||
branch:
|
||||
exclude:
|
||||
- master
|
||||
|
||||
steps:
|
||||
- name: chown
|
||||
image: qpms/buildenv/alpine/pkgdnumlib
|
||||
pull: never
|
||||
commands:
|
||||
- chown -R qpmsbuild.qpmsbuild .
|
||||
- name: submodules
|
||||
image: qpms/buildenv/alpine/pkgdnumlib
|
||||
pull: never
|
||||
user: qpmsbuild
|
||||
commands:
|
||||
- git submodule init
|
||||
- git submodule update
|
||||
- name: build
|
||||
image: qpms/buildenv/alpine/pkgdnumlib
|
||||
pull: never
|
||||
user: qpmsbuild
|
||||
commands:
|
||||
- cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local .
|
||||
- make install
|
||||
- export LIBRARY_PATH=$HOME/.local/lib
|
||||
- python3 setup.py install --user
|
||||
- cd examples/rectangular/modes
|
||||
- pip3 install --user matplotlib #needed to run the example
|
||||
- export LD_LIBRARY_PATH=$HOME/.local/lib
|
||||
- ./01a_realfreq_svd.sh
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: buildqpms-debian-preinstlibs
|
||||
|
||||
workspace:
|
||||
path: /home/qpmsbuild/qpms
|
||||
|
||||
steps:
|
||||
- name: chown
|
||||
image: qpms/buildenv/debian/pkgdnumlib
|
||||
pull: never
|
||||
commands:
|
||||
- chown -R qpmsbuild.qpmsbuild .
|
||||
- name: submodules
|
||||
image: qpms/buildenv/debian/pkgdnumlib
|
||||
pull: never
|
||||
user: qpmsbuild
|
||||
commands:
|
||||
- git submodule init
|
||||
- git submodule update
|
||||
- name: build
|
||||
image: qpms/buildenv/debian/pkgdnumlib
|
||||
pull: never
|
||||
user: qpmsbuild
|
||||
commands:
|
||||
- cmake -DCMAKE_INSTALL_PREFIX=/home/qpmsbuild/.local .
|
||||
- make install
|
||||
- export LIBRARY_PATH=$HOME/.local/lib
|
||||
- python3 setup.py install --user
|
||||
- pip3 install --user matplotlib #needed to run the examples
|
||||
- export LD_LIBRARY_PATH=$HOME/.local/lib
|
||||
- cd examples/rectangular/modes
|
||||
- ./01a_realfreq_svd.sh
|
||||
- cd -
|
||||
- cd examples/hexagonal/modes
|
||||
#- ./01a_realfreq_svd.sh
|
||||
#- ./01_compute_modes.sh
|
||||
#- ./02b_compute_disp_0M.sh
|
||||
#- ./02_compute_disp.sh
|
||||
#- ./02x_compute_disp.sh
|
||||
|
|
@ -5,4 +5,29 @@
|
|||
*.pdf
|
||||
*.o
|
||||
docs/*
|
||||
|
||||
qpms/qpms_c.c
|
||||
qpms/cy*.c
|
||||
CMakeCache.txt
|
||||
CMakeFiles/*
|
||||
faddeeva/*
|
||||
qpms/CMakeFiles/*
|
||||
qpms/libqpms.so
|
||||
qpms/cmake_install.cmake
|
||||
qpms_version.c
|
||||
qpms.egg_info/*
|
||||
dist/*
|
||||
build/*
|
||||
Makefile
|
||||
CTestTestfile.cmake
|
||||
|
||||
amos/CMakeFiles/*
|
||||
amos/Makefile
|
||||
amos/amos_mangling.h
|
||||
cmake_install.cmake
|
||||
cython_debug/*
|
||||
qpms.egg-info/*
|
||||
tests/CmakeFiles/*
|
||||
tests/cmake_install.cmake
|
||||
tests/CMakeFiles/*
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[submodule "camos"]
|
||||
path = camos
|
||||
url = https://codeberg.org/QPMS/zbessel.git
|
||||
branch = purec
|
|
@ -0,0 +1,43 @@
|
|||
Overview of QPMS command line utilities
|
||||
=======================================
|
||||
|
||||
The utilities are located in the `misc` directory. Run the
|
||||
utility with `-h` argument to get more info.
|
||||
|
||||
|
||||
Rectangular and square 2D lattices
|
||||
----------------------------------
|
||||
|
||||
These scripts deal with simple 2D rectangular lattices,
|
||||
finite or infinite, one scatterer per unit cell.
|
||||
\f$ D_{2h} \f$ or \f$ D_{4h} \f$ symmetric adapted bases
|
||||
are used where applicable.
|
||||
|
||||
### Finite lattices
|
||||
|
||||
* `finiterectlat-modes.py`: Search for resonances using Beyn's algorithm.
|
||||
* `finiterectlat-scatter.py`: Plane wave scattering.
|
||||
* `finiterectlat-constant-driving.py`: Rectangular array response to
|
||||
a driving where a subset of particles are excited by basis VSWFs with the
|
||||
same phase.
|
||||
|
||||
### Infinite lattices
|
||||
|
||||
* `rectlat_simple_modes.py`: Search for lattice modes using Beyn's algorithm.
|
||||
* `infiniterectlat-k0realfreqsvd.py`:
|
||||
Evaluate the lattice mode problem singular values at the Γ point for a real frequency interval.
|
||||
Useful as a starting point in lattice mode search before using Beyn's algorithm.
|
||||
* `infiniterectlat-scatter.py`: Plane wave scattering.
|
||||
|
||||
|
||||
General 2D lattices
|
||||
-------------------
|
||||
|
||||
### Infinite lattices
|
||||
|
||||
These can contain several scatterers per unit cell. Symmetry adapted bases currently not implemented.
|
||||
|
||||
* `lat2d_modes.py`: Search for lattice modes using Beyn's algorithm.
|
||||
* `lat2d_realfreqsvd.py`:
|
||||
Evaluate the lattice mode problem singular values at the Γ point for a real frequency interval.
|
||||
Useful as a starting point in lattice mode search before using Beyn's algorithm.
|
|
@ -1,10 +1,17 @@
|
|||
cmake_minimum_required(VERSION 3.0.2)
|
||||
|
||||
option(QPMS_USE_FORTRAN_AMOS "Use the original AMOS Fortran libraries instead of the C ones" OFF)
|
||||
|
||||
if (QPMS_USE_FORTRAN_AMOS)
|
||||
include(CMakeAddFortranSubdirectory)
|
||||
endif (QPMS_USE_FORTRAN_AMOS)
|
||||
include(version.cmake)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
project (QPMS)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||
|
||||
macro(use_c99)
|
||||
if (CMAKE_VERSION VERSION_LESS "3.1")
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
|
@ -22,10 +29,23 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|||
|
||||
set (QPMS_VERSION_MAJOR 0)
|
||||
#set (QPMS_VERSION_MINOR 3)
|
||||
cmake_add_fortran_subdirectory (amos
|
||||
PROJECT amos
|
||||
LIBRARIES amos
|
||||
NO_EXTERNAL_INSTALL)
|
||||
|
||||
if (QPMS_USE_FORTRAN_AMOS)
|
||||
cmake_add_fortran_subdirectory (amos
|
||||
PROJECT amos
|
||||
LIBRARIES amos
|
||||
NO_EXTERNAL_INSTALL)
|
||||
set(QPMS_AMOSLIB amos)
|
||||
else (QPMS_USE_FORTRAN_AMOS)
|
||||
set(CAMOS_BUILD_STATIC ON)
|
||||
add_subdirectory (camos)
|
||||
set(QPMS_AMOSLIB camos)
|
||||
endif (QPMS_USE_FORTRAN_AMOS)
|
||||
|
||||
|
||||
set(FADDEEVA_BUILD_STATIC ON)
|
||||
add_subdirectory(faddeeva)
|
||||
|
||||
add_subdirectory (qpms)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,675 @@
|
|||
### GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
<https://fsf.org/>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
### Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom
|
||||
to share and change all versions of a program--to make sure it remains
|
||||
free software for all its users. We, the Free Software Foundation, use
|
||||
the GNU General Public License for most of our software; it applies
|
||||
also to any other work released this way by its authors. You can apply
|
||||
it to your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you
|
||||
have certain responsibilities if you distribute copies of the
|
||||
software, or if you modify it: responsibilities to respect the freedom
|
||||
of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the
|
||||
manufacturer can do so. This is fundamentally incompatible with the
|
||||
aim of protecting users' freedom to change the software. The
|
||||
systematic pattern of such abuse occurs in the area of products for
|
||||
individuals to use, which is precisely where it is most unacceptable.
|
||||
Therefore, we have designed this version of the GPL to prohibit the
|
||||
practice for those products. If such problems arise substantially in
|
||||
other domains, we stand ready to extend this provision to those
|
||||
domains in future versions of the GPL, as needed to protect the
|
||||
freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish
|
||||
to avoid the special danger that patents applied to a free program
|
||||
could make it effectively proprietary. To prevent this, the GPL
|
||||
assures that patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
### TERMS AND CONDITIONS
|
||||
|
||||
#### 0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds
|
||||
of works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of
|
||||
an exact copy. The resulting work is called a "modified version" of
|
||||
the earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user
|
||||
through a computer network, with no transfer of a copy, is not
|
||||
conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices" to
|
||||
the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
#### 1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work for
|
||||
making modifications to it. "Object code" means any non-source form of
|
||||
a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users can
|
||||
regenerate automatically from other parts of the Corresponding Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that same
|
||||
work.
|
||||
|
||||
#### 2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not convey,
|
||||
without conditions so long as your license otherwise remains in force.
|
||||
You may convey covered works to others for the sole purpose of having
|
||||
them make modifications exclusively for you, or provide you with
|
||||
facilities for running those works, provided that you comply with the
|
||||
terms of this License in conveying all material for which you do not
|
||||
control copyright. Those thus making or running the covered works for
|
||||
you must do so exclusively on your behalf, under your direction and
|
||||
control, on terms that prohibit them from making any copies of your
|
||||
copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under the
|
||||
conditions stated below. Sublicensing is not allowed; section 10 makes
|
||||
it unnecessary.
|
||||
|
||||
#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such
|
||||
circumvention is effected by exercising rights under this License with
|
||||
respect to the covered work, and you disclaim any intention to limit
|
||||
operation or modification of the work as a means of enforcing, against
|
||||
the work's users, your or third parties' legal rights to forbid
|
||||
circumvention of technological measures.
|
||||
|
||||
#### 4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
#### 5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these
|
||||
conditions:
|
||||
|
||||
- a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
- b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under
|
||||
section 7. This requirement modifies the requirement in section 4
|
||||
to "keep intact all notices".
|
||||
- c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
- d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
#### 6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms of
|
||||
sections 4 and 5, provided that you also convey the machine-readable
|
||||
Corresponding Source under the terms of this License, in one of these
|
||||
ways:
|
||||
|
||||
- a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
- b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the Corresponding
|
||||
Source from a network server at no charge.
|
||||
- c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
- d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
- e) Convey the object code using peer-to-peer transmission,
|
||||
provided you inform other peers where the object code and
|
||||
Corresponding Source of the work are being offered to the general
|
||||
public at no charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal,
|
||||
family, or household purposes, or (2) anything designed or sold for
|
||||
incorporation into a dwelling. In determining whether a product is a
|
||||
consumer product, doubtful cases shall be resolved in favor of
|
||||
coverage. For a particular product received by a particular user,
|
||||
"normally used" refers to a typical or common use of that class of
|
||||
product, regardless of the status of the particular user or of the way
|
||||
in which the particular user actually uses, or expects or is expected
|
||||
to use, the product. A product is a consumer product regardless of
|
||||
whether the product has substantial commercial, industrial or
|
||||
non-consumer uses, unless such uses represent the only significant
|
||||
mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to
|
||||
install and execute modified versions of a covered work in that User
|
||||
Product from a modified version of its Corresponding Source. The
|
||||
information must suffice to ensure that the continued functioning of
|
||||
the modified object code is in no case prevented or interfered with
|
||||
solely because modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or
|
||||
updates for a work that has been modified or installed by the
|
||||
recipient, or for the User Product in which it has been modified or
|
||||
installed. Access to a network may be denied when the modification
|
||||
itself materially and adversely affects the operation of the network
|
||||
or violates the rules and protocols for communication across the
|
||||
network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
#### 7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders
|
||||
of that material) supplement the terms of this License with terms:
|
||||
|
||||
- a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
- b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
- c) Prohibiting misrepresentation of the origin of that material,
|
||||
or requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
- d) Limiting the use for publicity purposes of names of licensors
|
||||
or authors of the material; or
|
||||
- e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
- f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions
|
||||
of it) with contractual assumptions of liability to the recipient,
|
||||
for any liability that these contractual assumptions directly
|
||||
impose on those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions; the
|
||||
above requirements apply either way.
|
||||
|
||||
#### 8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your license
|
||||
from a particular copyright holder is reinstated (a) provisionally,
|
||||
unless and until the copyright holder explicitly and finally
|
||||
terminates your license, and (b) permanently, if the copyright holder
|
||||
fails to notify you of the violation by some reasonable means prior to
|
||||
60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
#### 9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or run
|
||||
a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
#### 10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
#### 11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims owned
|
||||
or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within the
|
||||
scope of its coverage, prohibits the exercise of, or is conditioned on
|
||||
the non-exercise of one or more of the rights that are specifically
|
||||
granted under this License. You may not convey a covered work if you
|
||||
are a party to an arrangement with a third party that is in the
|
||||
business of distributing software, under which you make payment to the
|
||||
third party based on the extent of your activity of conveying the
|
||||
work, and under which the third party grants, to any of the parties
|
||||
who would receive the covered work from you, a discriminatory patent
|
||||
license (a) in connection with copies of the covered work conveyed by
|
||||
you (or copies made from those copies), or (b) primarily for and in
|
||||
connection with specific products or compilations that contain the
|
||||
covered work, unless you entered into that arrangement, or that patent
|
||||
license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
#### 12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under
|
||||
this License and any other pertinent obligations, then as a
|
||||
consequence you may not convey it at all. For example, if you agree to
|
||||
terms that obligate you to collect a royalty for further conveying
|
||||
from those to whom you convey the Program, the only way you could
|
||||
satisfy both those terms and this License would be to refrain entirely
|
||||
from conveying the Program.
|
||||
|
||||
#### 13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
#### 14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in
|
||||
detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies that a certain numbered version of the GNU General Public
|
||||
License "or any later version" applies to it, you have the option of
|
||||
following the terms and conditions either of that numbered version or
|
||||
of any later version published by the Free Software Foundation. If the
|
||||
Program does not specify a version number of the GNU General Public
|
||||
License, you may choose any version ever published by the Free
|
||||
Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future versions
|
||||
of the GNU General Public License can be used, that proxy's public
|
||||
statement of acceptance of a version permanently authorizes you to
|
||||
choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
#### 15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
|
||||
WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
|
||||
PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
|
||||
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
|
||||
CORRECTION.
|
||||
|
||||
#### 16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR
|
||||
CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
|
||||
ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
|
||||
NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
|
||||
LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
|
||||
TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
|
||||
PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
#### 17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
### How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these
|
||||
terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to
|
||||
attach them to the start of each source file to most effectively state
|
||||
the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper
|
||||
mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands \`show w' and \`show c' should show the
|
||||
appropriate parts of the General Public License. Of course, your
|
||||
program's commands might be different; for a GUI interface, you would
|
||||
use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. For more information on this, and how to apply and follow
|
||||
the GNU GPL, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your
|
||||
program into proprietary programs. If your program is a subroutine
|
||||
library, you may consider it more useful to permit linking proprietary
|
||||
applications with the library. If this is what you want to do, use the
|
||||
GNU Lesser General Public License instead of this License. But first,
|
||||
please read <https://www.gnu.org/licenses/why-not-lgpl.html>.
|
8
Doxyfile
8
Doxyfile
|
@ -51,7 +51,7 @@ PROJECT_BRIEF = "Electromagnetic multiple scattering library and toolki
|
|||
# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
|
||||
# to the output directory.
|
||||
|
||||
PROJECT_LOGO =
|
||||
PROJECT_LOGO = farfield.png
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
|
||||
# into which the generated documentation will be written. If a relative path is
|
||||
|
@ -753,7 +753,7 @@ WARN_LOGFILE =
|
|||
# spaces.
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = qpms notes finite_systems.md README.md README.Triton.md finite_systems.md lattices.md TODO.md
|
||||
INPUT = qpms notes misc finite_systems.md MIRRORS.md CLIUTILS.md README.md README.Triton.md finite_systems.md lattices.md TODO.md
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
|
@ -773,7 +773,7 @@ INPUT_ENCODING = UTF-8
|
|||
# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
|
||||
# *.qsf, *.as and *.js.
|
||||
|
||||
FILE_PATTERNS =
|
||||
FILE_PATTERNS =
|
||||
|
||||
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
||||
# be searched for input files as well.
|
||||
|
@ -1462,7 +1462,7 @@ MATHJAX_FORMAT = HTML-CSS
|
|||
# The default value is: http://cdn.mathjax.org/mathjax/latest.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
MATHJAX_RELPATH = https://uslugi.necada.org/js/mathjax
|
||||
|
||||
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
|
||||
# extension names that should be enabled during MathJax rendering. For example
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
QPMS source code mirrors
|
||||
========================
|
||||
|
||||
QPMS source code is available at several locations; in all of the following,
|
||||
upstream `master` branch is kept up-to-date. Various development branches
|
||||
are not necessarily pushed everywhere (and they should be considered
|
||||
unstable in the sense that rebases and forced pushes are possible).
|
||||
|
||||
mirror | note | provider | backend
|
||||
----------------------------------------------- | ----------------------- | ------------------------------------------------- | ------
|
||||
<https://repo.or.cz/qpms.git> | primary public upstream | [repo.or.cz](https://repo.or.cz/) | girocco
|
||||
<https://codeberg.org/QPMS/qpms> | | [Codeberg](https://codeberg.org) | gitea
|
||||
<https://git.piraattipuolue.fi/QPMS/qpms.git> | | [Pirate Party Finland](https://piraattipuolue.fi) | gitea
|
||||
<https://version.aalto.fi/gitlab/qpms/qpms.git> | | [Aalto University](https://aalto.fi) | gitlab
|
127
README.md
127
README.md
|
@ -1,10 +1,14 @@
|
|||
[![Build Status](https://drone.perkele.eu/api/badges/QPMS/qpms/status.svg)](https://drone.perkele.eu/QPMS/qpms)
|
||||
|
||||
QPMS README
|
||||
===========
|
||||
|
||||
QPMS is a toolkit for frequency-domain simulations of photonic systems
|
||||
[QPMS][homepage] (standing for QPMS Photonic Multiple Scattering)
|
||||
is a toolkit for frequency-domain simulations of photonic systems
|
||||
consisting of compact objects (particles) inside a homogeneous medium. Scattering
|
||||
properties of the individual particles are described by their T-matrices
|
||||
(which can be obtained e.g. with the `scuff-tmatrix` tool from
|
||||
(which can be obtained using one of the built-in generators or
|
||||
e.g. with the `scuff-tmatrix` tool from
|
||||
the [SCUFF-EM] suite).
|
||||
|
||||
QPMS handles the multiple scattering of electromagnetic radiation between
|
||||
|
@ -12,26 +16,39 @@ the particles. The system can consist either of a finite number of particles
|
|||
or an infinite number of periodically arranged lattices (with finite number
|
||||
of particles in a single unit cell).
|
||||
|
||||
|
||||
Features
|
||||
========
|
||||
|
||||
|
||||
Finite systems
|
||||
--------------
|
||||
* Computing multipole excitations *and fields (TODO)* scattered from nanoparticle
|
||||
* Computing multipole excitations and fields scattered from nanoparticle
|
||||
clusters illuminated by plane, spherical or *cylindrical (TODO)* waves.
|
||||
* Finding eigenmodes.
|
||||
* *Calculating cross sections (TODO).*
|
||||
* Finding eigenmodes (optical resonances).
|
||||
* Calculating cross sections.
|
||||
* Reducing numerical complexity of the computations by exploiting
|
||||
symmetries of the cluster (decomposition to irreducible representations).
|
||||
|
||||
|
||||
Infinite systems (lattices)
|
||||
---------------------------
|
||||
* 2D-periodic systems supported. (TODO 1D and 3D.)
|
||||
* *Calculation of transmission and reflection properties (TODO).*
|
||||
* 2D-periodic systems with arbitrary unit cell geometry supported. (TODO 1D and 3D.)
|
||||
* Computing multipole excitations and fields scattered from nanoparticle
|
||||
* Finding eigenmodes and calculating dispersion relations.
|
||||
* *Calculation of far-field radiation patterns of an excited array (TODO).*
|
||||
* Reducing numerical complexity of the computations by exploiting
|
||||
symmetries of the lattice (decomposition to irreducible representations).
|
||||
* Calculation of the scattered fields.
|
||||
* *Calculation of total transmission and reflection properties (TODO).*
|
||||
* *Reducing numerical complexity of the computations by exploiting
|
||||
symmetries of the lattice (decomposition to irreducible representations) (in development).*
|
||||
|
||||
|
||||
Getting the code
|
||||
================
|
||||
|
||||
The codebase is available at the main upstream public repository
|
||||
<https://repo.or.cz/qpms.git> or any of the [maintained mirrors][MIRRORS].
|
||||
Just clone the repository with `git` and proceed to the installation instructions
|
||||
below.
|
||||
|
||||
|
||||
Installation
|
||||
|
@ -47,7 +64,16 @@ you can [get the source and compile it yourself][GSL].
|
|||
|
||||
You also need a fresh enough version of [cmake][].
|
||||
|
||||
After GSL is installed, you can install qpms to your local python library using
|
||||
QPMS uses a C version of the Amos library for calculating Bessel function
|
||||
from a submodule. Before proceeding with running `cmake`, the submodules
|
||||
need to be downloaded first (in the QPMS source root directory):
|
||||
|
||||
```{.sh}
|
||||
git submodule init
|
||||
git submodule update
|
||||
```
|
||||
|
||||
After GSL is installed and submodules updated, you can install qpms to your local python library using
|
||||
|
||||
```{.sh}
|
||||
cmake -DCMAKE_INSTALL_PREFIX=${YOUR_PREFIX} .
|
||||
|
@ -66,13 +92,21 @@ Special care might need to be taken when installing QPMS in cluster environments
|
|||
Specific installation instructions for Aalto University's Triton cluster
|
||||
can be found in a [separate document][TRITON-README].
|
||||
|
||||
Instructions for installation on Android-based devices are
|
||||
in [another document][INSTALL-ANDROID].
|
||||
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
Documentation of QPMS is a work in progress. Most of the newer code
|
||||
is documented using [doxygen][] comments. To build the documentation, just run
|
||||
[QPMS documentation][homepage] is a work in progress. Most of the newer code
|
||||
is documented using [doxygen][] comments. Documentation generated for the
|
||||
upstream version is hosted on the QPMS homepage <https://qpms.necada.org>.
|
||||
|
||||
To build the documentation yourself,
|
||||
just run
|
||||
`doxygen`
|
||||
in the root directory; the documentation will then be found in
|
||||
in the QPMS source root directory; the documentation will then be found in
|
||||
`docs/html/index.html`.
|
||||
|
||||
Of course, the prerequisite of this is having doxygen installed.
|
||||
|
@ -84,14 +118,77 @@ under root.
|
|||
Tutorials
|
||||
---------
|
||||
|
||||
* [Infinite system (lattice) tutorial][tutorial-infinite]
|
||||
* [Finite system tutorial][tutorial-finite]
|
||||
|
||||
See also the examples directory in the source repository.
|
||||
|
||||
|
||||
Command line utilities
|
||||
----------------------
|
||||
|
||||
* [Overview of the Python command line utilities][cliutils]
|
||||
|
||||
|
||||
Acknowledgments
|
||||
================
|
||||
|
||||
This software has been developed in the [Quantum Dynamics research group][QD],
|
||||
Aalto University, Finland. If you use the code in your work, please cite
|
||||
**M. Nečada and P. Törmä, Multiple-scattering T-matrix simulations for nanophotonics: symmetries and periodic lattices, [arXiv: 2006.12968][lepaper] (2020)**
|
||||
in your publications, presentations, and similar.
|
||||
|
||||
Please also have a look at other publications by the group
|
||||
(google scholar Päivi Törmä), they may be useful for your work as well.
|
||||
|
||||
|
||||
Bug reports
|
||||
===========
|
||||
|
||||
If you believe that some parts of QPMS behave incorrectly, please mail
|
||||
a bug report to [marek@necada.org][authormail]. To ensure that your message is not
|
||||
considered spam, please start the subject line with `QPMS`.
|
||||
|
||||
If you were able to fix a bug yourself, please include the patch as well,
|
||||
see below.
|
||||
|
||||
|
||||
Contributions
|
||||
=============
|
||||
|
||||
Contributions to QPMS are welcome, be it bug fixes, improvements to the
|
||||
documentation, code quality, or new features.
|
||||
|
||||
You can send patches prepared using the
|
||||
[`git format-patch`](https://git-scm.com/docs/git-format-patch) tool
|
||||
to [marek@necada.org][authormail].
|
||||
|
||||
If you plan to contribute with major changes to the codebase, it is
|
||||
recommended to discuss that first (see the contact information below).
|
||||
|
||||
|
||||
Contact & discussion
|
||||
====================
|
||||
|
||||
You can contact the main author e.g. via [e-mail][authormail]
|
||||
or [Telegram](https://t.me/necadam).
|
||||
|
||||
You are also warmly welcome to the [QPMS user chat][telegramchat]
|
||||
in Telegram!
|
||||
|
||||
|
||||
[homepage]: https://qpms.necada.org
|
||||
[SCUFF-EM]: https://homerreid.github.io/scuff-em-documentation/
|
||||
[OpenBLAS]: https://www.openblas.net/
|
||||
[GSL]: https://www.gnu.org/software/gsl/
|
||||
[cmake]: https://cmake.org
|
||||
[TRITON-README]: README.Triton.md
|
||||
[INSTALL-ANDROID]: notes/INSTALL_ANDROID.md
|
||||
[tutorial-finite]: finite_systems.md
|
||||
[tutorial-infinite]: lattices.md
|
||||
[doxygen]: http://doxygen.nl/
|
||||
[QD]: https://www.aalto.fi/en/department-of-applied-physics/quantum-dynamics-qd
|
||||
[lepaper]: https://arxiv.org/abs/2006.12968
|
||||
[telegramchat]: https://t.me/QPMScattering
|
||||
[authormail]: mailto:marek@necada.org
|
||||
[cliutils]: CLIUTILS.md
|
||||
[MIRRORS]: MIRRORS.md
|
||||
|
|
29
TODO.md
29
TODO.md
|
@ -1,11 +1,12 @@
|
|||
TODO list before public release
|
||||
===============================
|
||||
TODO list before 1.0 release
|
||||
============================
|
||||
|
||||
- Tests!
|
||||
- Docs!
|
||||
- Cross section calculations.
|
||||
- Field calculations.
|
||||
- Complex frequencies, n's, k's.
|
||||
- Cross section calculations. (Done in some Python scripts.)
|
||||
- Field calculations. (Partly done, needs more testing.)
|
||||
* Also test periodic vs. nonperiodic consistence (big finite lattice + absorbing medium vs. infinite lattice + absorbing medium).
|
||||
- Complex frequencies, n's, k's. (Mostly done.)
|
||||
- Transforming point (meta)generators.
|
||||
- Check whether moble's quaternions and my
|
||||
quaternions give the same results in tmatrices.py
|
||||
|
@ -24,11 +25,12 @@ TODO list before public release
|
|||
* As a description of a T-matrix / particle metadata.
|
||||
- Nice CLI for all general enough utilities.
|
||||
- Remove legacy code.
|
||||
- Split qpms_c.pyx.
|
||||
- Split `qpms_c.pyx`.
|
||||
- Reduce compiler warnings.
|
||||
- Serialisation (saving, loading) of `ScatteringSystem` and other structures.
|
||||
- Python exceptions instead of hard crashes in the C library where possible.
|
||||
- Scatsystem init sometimes fail due to rounding errors and hardcoded absolute tolerance
|
||||
in the qpms_tmatrix_isclose() call.
|
||||
in the `qpms_tmatrix_isclose()` call.
|
||||
- Prefix all identifiers. Maybe think about a different prefix than qpms?
|
||||
- Consistent indentation and style overall.
|
||||
- Rewrite the parallelized translation matrix, mode problem matrix generators
|
||||
|
@ -39,3 +41,16 @@ Nice but less important features
|
|||
|
||||
- Static, thread-safe caches of constant coefficients + API without the current "calculators".
|
||||
|
||||
|
||||
Optimisations
|
||||
-------------
|
||||
|
||||
- Leaving out the irrelevant elements if a "rectangular" block of the translations matrix is needed.
|
||||
- Ewald sums with "non-parallel" shifts (are about 20 times slower than the purely parallel ones).
|
||||
- Reusing intermediate results (profiling needed)
|
||||
* Bessel, Legendre functions (see also branch `finite_lattice_speedup`)
|
||||
* Lattice points (sorting and scaling)
|
||||
* Γ/Δ functions (for periodic lattices)
|
||||
- More parallelisation.
|
||||
- Possibly pre-calculation of the (precise) coefficients in Bessel and Legendre functions (using gmp)
|
||||
- Asymptotic approximations of the Bessel functions for far fields.
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef CAMOS_H_
|
||||
#define CAMOS_H_
|
||||
#include "amos.h"
|
||||
|
||||
// TODO what about all the INTEGER_t and DOUBLE_PRECISION_t?
|
||||
|
||||
static inline int camos_zbesh(double zr, double zi, double fnu, int kode, int m,
|
||||
int n, double *cyr, double *cyi, int *nz) {
|
||||
int ierr;
|
||||
amos_zbesh(&zr, &zi, &fnu, &kode, &m, &n, cyr, cyi, nz, &ierr);
|
||||
return ierr;
|
||||
}
|
||||
|
||||
static inline int camos_zbesj(double zr, double zi, double fnu, int kode, int n, double *cyr,
|
||||
double *cyi, int *nz) {
|
||||
int ierr;
|
||||
double cwrkr[n], cwrki[n];
|
||||
amos_zbesj(&zr, &zi, &fnu, &kode, &n, cyr, cyi, nz, &ierr);
|
||||
return ierr;
|
||||
}
|
||||
|
||||
static inline int camos_zbesy(double zr, double zi, double fnu, int kode, int n, double *cyr,
|
||||
double *cyi, int *nz, double *cwrkr, double *cwrki) {
|
||||
int ierr;
|
||||
amos_zbesy(&zr, &zi, &fnu, &kode, &n, cyr, cyi, nz, cwrkr, cwrki, &ierr);
|
||||
return ierr;
|
||||
}
|
||||
|
||||
|
||||
#endif // CAMOS_H_
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 19e7ae82e7e0b436bd273557a87d288f8f338221
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
DP=Dockerfile_parts
|
||||
# "Build environment" Dockerfiles
|
||||
cat >Dockerfile.benv.debian.bnl ${DP}/00_common.debian ${DP}/01_numlibs.built
|
||||
cat >Dockerfile.benv.debian.pnl ${DP}/00_common.debian ${DP}/01_numlibs.debian.pkgd
|
||||
cat >Dockerfile.benv.alpine.bnl ${DP}/00_common.alpine ${DP}/01_numlibs.built
|
||||
cat >Dockerfile.benv.alpine.pnl ${DP}/00_common.alpine ${DP}/01_numlibs.alpine.pkgd
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
docker build -t qpms/buildenv/debian/builtnumlib -f Dockerfile.benv.debian.bnl .
|
||||
docker build -t qpms/buildenv/debian/pkgdnumlib -f Dockerfile.benv.debian.pnl .
|
||||
docker build -t qpms/buildenv/alpine/builtnumlib -f Dockerfile.benv.alpine.bnl .
|
||||
docker build -t qpms/buildenv/alpine/pkgdnumlib -f Dockerfile.benv.alpine.pnl .
|
|
@ -0,0 +1,5 @@
|
|||
FROM alpine:latest AS commondeps
|
||||
RUN apk update \
|
||||
&& apk add cmake python3-dev py3-pip gcc g++ wget git make libc-dev bc \
|
||||
&& adduser -D qpmsbuild
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
FROM debian:stable AS commondeps
|
||||
RUN apt-get update \
|
||||
&& apt-get -y install --no-install-recommends build-essential cmake python3 python3-pip git wget python3-dev bc \
|
||||
&& apt-get clean \
|
||||
&& useradd -m qpmsbuild
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
FROM commondeps AS numlibs
|
||||
# openblas-dev adds gfortran :(
|
||||
RUN apk add openblas-dev gsl-dev
|
|
@ -0,0 +1,16 @@
|
|||
FROM commondeps AS buildopenblas
|
||||
USER qpmsbuild
|
||||
RUN cd && git clone --depth 1 https://github.com/xianyi/OpenBLAS.git \
|
||||
&& cd OpenBLAS && make \
|
||||
&& make install PREFIX=$HOME/.local/ \
|
||||
&& make clean \
|
||||
&& cd .. && rm -rf OpenBLAS
|
||||
|
||||
FROM buildopenblas AS numlibs
|
||||
USER qpmsbuild
|
||||
RUN cd && wget https://ftp.gnu.org/gnu/gsl/gsl-latest.tar.gz \
|
||||
&& tar xf gsl-latest.tar.gz \
|
||||
&& cd $( tar tf gsl-latest.tar.gz | head -n 1 ) \
|
||||
&& ./configure --prefix=$HOME/.local \
|
||||
&& make && make install && make clean \
|
||||
&& cd .. && rm -rf $OLDPWD gsl-latest.tar.gz
|
|
@ -0,0 +1,4 @@
|
|||
FROM commondeps AS numlibs
|
||||
RUN apt-get -y install --no-install-recommends libopenblas-dev libgsl-dev liblapacke-dev \
|
||||
&& apt-get clean
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
FROM numlibs AS buildqpms
|
||||
USER qpmsbuild
|
||||
ENV LD_LIBRARY_PATH /home/qpmsbuild/.local/lib
|
||||
ENV LIBRARY_PATH /home/qpmsbuild/.local/lib
|
||||
ENV C_INCLUDE_PATH /home/qpmsbuild/.local/include
|
||||
RUN cd && git clone --depth 1 https://repo.or.cz/qpms.git \
|
||||
&& cd qpms && git submodule init && git submodule update
|
||||
RUN cd ~/qpms && cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local . \
|
||||
&& make \
|
||||
&& make install
|
||||
RUN cd ~/qpms && python3 setup.py install --user
|
||||
|
|
@ -0,0 +1 @@
|
|||
../.drone.yml
|
|
@ -0,0 +1,284 @@
|
|||
# - Returns a version string from Git
|
||||
#
|
||||
# These functions force a re-configure on each git commit so that you can
|
||||
# trust the values of the variables in your build system.
|
||||
#
|
||||
# get_git_head_revision(<refspecvar> <hashvar> [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR])
|
||||
#
|
||||
# Returns the refspec and sha hash of the current head revision
|
||||
#
|
||||
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the source tree, and adjusting
|
||||
# the output so that it tests false if an error occurs.
|
||||
#
|
||||
# git_describe_working_tree(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the working tree (--dirty option),
|
||||
# and adjusting the output so that it tests false if an error occurs.
|
||||
#
|
||||
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe --exact-match on the source tree,
|
||||
# and adjusting the output so that it tests false if there was no exact
|
||||
# matching tag.
|
||||
#
|
||||
# git_local_changes(<var>)
|
||||
#
|
||||
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
|
||||
# Uses the return code of "git diff-index --quiet HEAD --".
|
||||
# Does not regard untracked files.
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
#
|
||||
# Copyright 2009-2013, Iowa State University.
|
||||
# Copyright 2013-2020, Ryan Pavlik
|
||||
# Copyright 2013-2020, Contributors
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
if(__get_git_revision_description)
|
||||
return()
|
||||
endif()
|
||||
set(__get_git_revision_description YES)
|
||||
|
||||
# We must run the following at "include" time, not at function call time,
|
||||
# to find the path to this module rather than the path to a calling list file
|
||||
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
|
||||
# Function _git_find_closest_git_dir finds the next closest .git directory
|
||||
# that is part of any directory in the path defined by _start_dir.
|
||||
# The result is returned in the parent scope variable whose name is passed
|
||||
# as variable _git_dir_var. If no .git directory can be found, the
|
||||
# function returns an empty string via _git_dir_var.
|
||||
#
|
||||
# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
|
||||
# neither foo nor bar contain a file/directory .git. This wil return
|
||||
# C:/bla/.git
|
||||
#
|
||||
function(_git_find_closest_git_dir _start_dir _git_dir_var)
|
||||
set(cur_dir "${_start_dir}")
|
||||
set(git_dir "${_start_dir}/.git")
|
||||
while(NOT EXISTS "${git_dir}")
|
||||
# .git dir not found, search parent directories
|
||||
set(git_previous_parent "${cur_dir}")
|
||||
get_filename_component(cur_dir "${cur_dir}" DIRECTORY)
|
||||
if(cur_dir STREQUAL git_previous_parent)
|
||||
# We have reached the root directory, we are not in git
|
||||
set(${_git_dir_var}
|
||||
""
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
set(git_dir "${cur_dir}/.git")
|
||||
endwhile()
|
||||
set(${_git_dir_var}
|
||||
"${git_dir}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(get_git_head_revision _refspecvar _hashvar)
|
||||
_git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
|
||||
|
||||
if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR")
|
||||
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE)
|
||||
else()
|
||||
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE)
|
||||
endif()
|
||||
if(NOT "${GIT_DIR}" STREQUAL "")
|
||||
file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
|
||||
"${GIT_DIR}")
|
||||
if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)
|
||||
# We've gone above the CMake root dir.
|
||||
set(GIT_DIR "")
|
||||
endif()
|
||||
endif()
|
||||
if("${GIT_DIR}" STREQUAL "")
|
||||
set(${_refspecvar}
|
||||
"GITDIR-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
set(${_hashvar}
|
||||
"GITDIR-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Check if the current source dir is a git submodule or a worktree.
|
||||
# In both cases .git is a file instead of a directory.
|
||||
#
|
||||
if(NOT IS_DIRECTORY ${GIT_DIR})
|
||||
# The following git command will return a non empty string that
|
||||
# points to the super project working tree if the current
|
||||
# source dir is inside a git submodule.
|
||||
# Otherwise the command will return an empty string.
|
||||
#
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" rev-parse
|
||||
--show-superproject-working-tree
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT "${out}" STREQUAL "")
|
||||
# If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule
|
||||
file(READ ${GIT_DIR} submodule)
|
||||
string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE
|
||||
${submodule})
|
||||
string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)
|
||||
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
||||
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}
|
||||
ABSOLUTE)
|
||||
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||
else()
|
||||
# GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree
|
||||
file(READ ${GIT_DIR} worktree_ref)
|
||||
# The .git directory contains a path to the worktree information directory
|
||||
# inside the parent git repo of the worktree.
|
||||
#
|
||||
string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir
|
||||
${worktree_ref})
|
||||
string(STRIP ${git_worktree_dir} git_worktree_dir)
|
||||
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
|
||||
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
|
||||
endif()
|
||||
else()
|
||||
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||
endif()
|
||||
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||
if(NOT EXISTS "${GIT_DATA}")
|
||||
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${HEAD_SOURCE_FILE}")
|
||||
return()
|
||||
endif()
|
||||
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
|
||||
|
||||
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||
"${GIT_DATA}/grabRef.cmake" @ONLY)
|
||||
include("${GIT_DATA}/grabRef.cmake")
|
||||
|
||||
set(${_refspecvar}
|
||||
"${HEAD_REF}"
|
||||
PARENT_SCOPE)
|
||||
set(${_hashvar}
|
||||
"${HEAD_HASH}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_describe _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var}
|
||||
"HEAD-HASH-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# TODO sanitize
|
||||
#if((${ARGN}" MATCHES "&&") OR
|
||||
# (ARGN MATCHES "||") OR
|
||||
# (ARGN MATCHES "\\;"))
|
||||
# message("Please report the following error to the project!")
|
||||
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||
#endif()
|
||||
|
||||
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT res EQUAL 0)
|
||||
set(out "${out}-${res}-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_describe_working_tree _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT res EQUAL 0)
|
||||
set(out "${out}-${res}-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_get_exact_tag _var)
|
||||
git_describe(out --exact-match ${ARGN})
|
||||
set(${_var}
|
||||
"${out}"
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_local_changes _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var}
|
||||
"GIT-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var}
|
||||
"HEAD-HASH-NOTFOUND"
|
||||
PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE res
|
||||
OUTPUT_VARIABLE out
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(res EQUAL 0)
|
||||
set(${_var}
|
||||
"CLEAN"
|
||||
PARENT_SCOPE)
|
||||
else()
|
||||
set(${_var}
|
||||
"DIRTY"
|
||||
PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
|
@ -0,0 +1,43 @@
|
|||
#
|
||||
# Internal file for GetGitRevisionDescription.cmake
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright 2009-2012, Iowa State University
|
||||
# Copyright 2011-2015, Contributors
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
set(HEAD_HASH)
|
||||
|
||||
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||
|
||||
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||
if(HEAD_CONTENTS MATCHES "ref")
|
||||
# named branch
|
||||
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
else()
|
||||
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
|
||||
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
|
||||
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
|
||||
set(HEAD_HASH "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
# detached HEAD
|
||||
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
endif()
|
||||
|
||||
if(NOT HEAD_HASH)
|
||||
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||
endif()
|
|
@ -0,0 +1,23 @@
|
|||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,36 @@
|
|||
#!/usr/bin/env python3
|
||||
from qpms import TMatrixGenerator, BaseSpec, eV, hbar
|
||||
import numpy as np
|
||||
import sys
|
||||
|
||||
errors = 0
|
||||
|
||||
def tmg_diagonal_fun(tmatrix, omega):
|
||||
'''
|
||||
Example of a python function used as a custom T-matrix generator
|
||||
|
||||
It receives a CTMatrix argument with pre-filled BaseSpec
|
||||
(in tmatrix.spec) and angular frequency.
|
||||
|
||||
It has to fill in the T-matrix elements tmatrix[...]
|
||||
(a numpy array of shape (len(tmatrix.spec),len(tmatrix.spec)))
|
||||
and return zero (on success) or other integral value on error.
|
||||
|
||||
Note that this in justa an example of using the API,
|
||||
not supposed to be anything physical.
|
||||
'''
|
||||
l = tmatrix.spec.l()
|
||||
tmatrix[...] = np.diag(1./l**2)
|
||||
return 0
|
||||
|
||||
# Wrap the function as an actual TMatrixGenerator
|
||||
tmg_diagonal = TMatrixGenerator(tmg_diagonal_fun)
|
||||
|
||||
bspec = BaseSpec(lMax=2)
|
||||
|
||||
tmatrix = tmg_diagonal(bspec, (2.0+.01j) * eV/hbar)
|
||||
|
||||
errors += np.sum(tmatrix[...] != np.diag(1./bspec.l()**2))
|
||||
|
||||
sys.exit(errors)
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#!/bin/bash
|
||||
echo 'scale=20;pi=3.14159265358979323846;' > bc_env
|
||||
export BC_ENV_ARGS="bc_env"
|
||||
|
||||
# We put those into bc, which does not understant exponential notation
|
||||
SEPARATION_nm=576
|
||||
|
||||
# Particle positions within unit cell
|
||||
export P1X_nm=0
|
||||
export P1Y_nm=$(bc <<< ${SEPARATION_nm}/2)
|
||||
export P2X_nm=0
|
||||
export P2Y_nm=-$P1Y_nm
|
||||
|
||||
# Lattice vectors
|
||||
export A1X_nm=$(bc <<< ${SEPARATION_nm}'*sqrt(3)')
|
||||
export A1Y_nm=0
|
||||
export A2X_nm=$(bc <<< ${SEPARATION_nm}'*sqrt(3)/2')
|
||||
export A2Y_nm=$(bc <<< ${SEPARATION_nm}'*3/2')
|
||||
|
||||
# Reciprocal lattice vectors
|
||||
export B1X_nmi=$(bc <<< '2*pi/sqrt(3)/'${SEPARATION_nm})
|
||||
export B1Y_nmi=$(bc <<< '-2*pi/3/'${SEPARATION_nm})
|
||||
export B2X_nmi=0
|
||||
export B2Y_nmi=$(bc <<< '4*pi/3/'${SEPARATION_nm})
|
||||
|
||||
# a K-point coordinates
|
||||
export KPOINTX_nmi=$(bc <<< '4*pi/3/sqrt(3)'/${SEPARATION_nm})
|
||||
export KPOINTY_nmi=0.0 #$(bc <<< '4*pi/3/sqrt(3)'/${SEPARATION_nm})
|
||||
|
||||
# a M-point coordinates
|
||||
export MPOINTX_nmi=0.0
|
||||
export MPOINTY_nmi=$(bc <<< '2*pi/3'/${SEPARATION_nm})
|
||||
|
||||
|
||||
export RADIUS_nm=50
|
||||
export HEIGHT_nm=50
|
||||
export METAL=Au
|
||||
export BG_REFINDEX=1.52
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
${MISCDIR}/lat2d_modes.py \
|
||||
-n $BG_REFINDEX \
|
||||
-b s${A1X_nm}e-9 s${A1Y_nm}e-9 \
|
||||
-b s${A2X_nm}e-9 s${A2Y_nm}e-9 \
|
||||
-p s${P1X_nm}e-9 s${P1Y_nm}e-9 \
|
||||
-p s${P2X_nm}e-9 s${P2Y_nm}e-9 \
|
||||
-L 3 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
-k s${KPOINTX_nmi}e9 s${KPOINTY_nmi}e9 \
|
||||
-d -3 \
|
||||
-t 0.01 \
|
||||
-c 250 \
|
||||
-P
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
${MISCDIR}/lat2d_realfreqsvd.py \
|
||||
-B $BG_REFINDEX \
|
||||
-b s${A1X_nm}e-9 s${A1Y_nm}e-9 \
|
||||
-b s${A2X_nm}e-9 s${A2Y_nm}e-9 \
|
||||
-p s${P1X_nm}e-9 s${P1Y_nm}e-9 \
|
||||
-p s${P2X_nm}e-9 s${P2Y_nm}e-9 \
|
||||
-L 3 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
-k s${KPOINTX_nmi}e9 s${KPOINTY_nmi}e9 \
|
||||
-F 1.3 0.001 1.5 \
|
||||
-P
|
|
@ -0,0 +1,22 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
for bbb in 1 -2 -3 -4 ; do
|
||||
for coeff in $(seq 0.80 0.01 1.50 | sed -e s/,/./g) ; do
|
||||
${MISCDIR}/lat2d_modes.py \
|
||||
-n $BG_REFINDEX \
|
||||
-b s${A1X_nm}e-9 s${A1Y_nm}e-9 \
|
||||
-b s${A2X_nm}e-9 s${A2Y_nm}e-9 \
|
||||
-p s${P1X_nm}e-9 s${P1Y_nm}e-9 \
|
||||
-p s${P2X_nm}e-9 s${P2Y_nm}e-9 \
|
||||
-L 3 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
-k s$(bc <<< ${KPOINTX_nmi}*${coeff})e9 s$(bc <<< ${KPOINTY_nmi}*${coeff})e9 \
|
||||
-d $bbb \
|
||||
-t 1e13 \
|
||||
-T 0.2 \
|
||||
-c 250
|
||||
done
|
||||
done
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
for bbb in 1 -2 -3 -4 ; do
|
||||
for coeff in $(seq 0.00 0.01 1.00 | sed -e s/,/./g) ; do
|
||||
${MISCDIR}/lat2d_modes.py \
|
||||
-n $BG_REFINDEX \
|
||||
-b s${A1X_nm}e-9 s${A1Y_nm}e-9 \
|
||||
-b s${A2X_nm}e-9 s${A2Y_nm}e-9 \
|
||||
-p s${P1X_nm}e-9 s${P1Y_nm}e-9 \
|
||||
-p s${P2X_nm}e-9 s${P2Y_nm}e-9 \
|
||||
-L 3 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
-k s$(bc <<< ${MPOINTX_nmi}*${coeff})e9 s$(bc <<< ${MPOINTY_nmi}*${coeff})e9 \
|
||||
-d $bbb \
|
||||
-t 1e12 \
|
||||
-T 0.3 \
|
||||
-c 250 \
|
||||
-P
|
||||
done
|
||||
done
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
for bbb in 1 2 ; do
|
||||
for coeff in $(seq 0.80 0.01 2.00 | sed -e s/,/./g) ; do
|
||||
${MISCDIR}/lat2d_modes.py \
|
||||
-n $BG_REFINDEX \
|
||||
-b s${A1X_nm}e-9 s${A1Y_nm}e-9 \
|
||||
-b s${A2X_nm}e-9 s${A2Y_nm}e-9 \
|
||||
-p s${P1X_nm}e-9 s${P1Y_nm}e-9 \
|
||||
-p s${P2X_nm}e-9 s${P2Y_nm}e-9 \
|
||||
-L 3 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
-k s$(bc <<< ${KPOINTX_nmi}*${coeff})e9 s$(bc <<< ${KPOINTY_nmi}*${coeff})e9 \
|
||||
-d -$bbb \
|
||||
-t 1e12 \
|
||||
-T 0.2 \
|
||||
-c 250 \
|
||||
-P
|
||||
done
|
||||
done
|
||||
|
|
@ -0,0 +1 @@
|
|||
scale=20;pi=3.14159265358979323846;
|
|
@ -0,0 +1,37 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Common parameters for a rectangular array
|
||||
# N.B. We put those into bc, which does not understant exponential notation
|
||||
|
||||
export PX_nm=375
|
||||
export PY_nm=375
|
||||
export RADIUS_nm=30
|
||||
export HEIGHT_nm=30
|
||||
export METAL=Ag
|
||||
export BG_REFINDEX=1.52
|
||||
|
||||
|
||||
# Setup bc
|
||||
|
||||
echo 'scale=20;pi=3.14159265358979323846;' > bc_env
|
||||
export BC_ENV_ARGS="bc_env"
|
||||
|
||||
|
||||
# We have only one particle per unit cell here
|
||||
export P1X_nm=0
|
||||
export P1Y_nm=0
|
||||
|
||||
|
||||
# Lattice vectors (for the general scripts)
|
||||
export A1X_nm=${PX_nm}
|
||||
export A1Y_nm=0
|
||||
export A2X_nm=0
|
||||
export A2Y_nm=${PY_nm}
|
||||
|
||||
# Reciprocal lattice vectors
|
||||
export B1X_nmi=$(bc <<< '1/'${PX_nm})
|
||||
export B1Y_nmi=0
|
||||
export B2X_nmi=0
|
||||
export B2Y_nmi=$(bc <<< '1/'${PY_nm})
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
${MISCDIR}/lat2d_modes.py \
|
||||
-n $BG_REFINDEX \
|
||||
-b s${A1X_nm}e-9 s${A1Y_nm}e-9 \
|
||||
-b s${A2X_nm}e-9 s${A2Y_nm}e-9 \
|
||||
-p s${P1X_nm}e-9 s${P1Y_nm}e-9 \
|
||||
-p s${P2X_nm}e-9 s${P2Y_nm}e-9 \
|
||||
-L 3 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
-k s${KPOINTX_nmi}e9 s${KPOINTY_nmi}e9 \
|
||||
-d -3 \
|
||||
-t 0.01 \
|
||||
-c 250 \
|
||||
-P
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
# try several lMaxes
|
||||
|
||||
${MISCDIR}/lat2d_realfreqsvd.py \
|
||||
-B $BG_REFINDEX \
|
||||
-b s${A1X_nm}e-9 s${A1Y_nm}e-9 \
|
||||
-b s${A2X_nm}e-9 s${A2Y_nm}e-9 \
|
||||
-p s${P1X_nm}e-9 s${P1Y_nm}e-9 \
|
||||
-L 2 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
-k 0 0 \
|
||||
-F 2.001 0.001 2.250 \
|
||||
-P
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
|
||||
for LMAX in 1 2 3 ; do # try several cutoffs
|
||||
${MISCDIR}/infiniterectlat-k0realfreqsvd.py \
|
||||
-B $BG_REFINDEX \
|
||||
-p ${PX_nm}e-9 ${PY_nm}e-9 \
|
||||
-L $LMAX -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
-F 2.001 0.001 2.250 \
|
||||
-P
|
||||
done
|
|
@ -0,0 +1,22 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
for bbb in 1 -2 -3 -4 ; do
|
||||
for coeff in $(seq 0.80 0.01 1.50 | sed -e s/,/./g) ; do
|
||||
${MISCDIR}/lat2d_modes.py \
|
||||
-n $BG_REFINDEX \
|
||||
-b s${A1X_nm}e-9 s${A1Y_nm}e-9 \
|
||||
-b s${A2X_nm}e-9 s${A2Y_nm}e-9 \
|
||||
-p s${P1X_nm}e-9 s${P1Y_nm}e-9 \
|
||||
-p s${P2X_nm}e-9 s${P2Y_nm}e-9 \
|
||||
-L 3 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
-k s$(bc <<< ${KPOINTX_nmi}*${coeff})e9 s$(bc <<< ${KPOINTY_nmi}*${coeff})e9 \
|
||||
-d $bbb \
|
||||
-t 1e13 \
|
||||
-T 0.2 \
|
||||
-c 250
|
||||
done
|
||||
done
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
for bbb in 1 -2 -3 -4 ; do
|
||||
for coeff in $(seq 0.00 0.01 1.00 | sed -e s/,/./g) ; do
|
||||
${MISCDIR}/lat2d_modes.py \
|
||||
-n $BG_REFINDEX \
|
||||
-b s${A1X_nm}e-9 s${A1Y_nm}e-9 \
|
||||
-b s${A2X_nm}e-9 s${A2Y_nm}e-9 \
|
||||
-p s${P1X_nm}e-9 s${P1Y_nm}e-9 \
|
||||
-p s${P2X_nm}e-9 s${P2Y_nm}e-9 \
|
||||
-L 3 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
-k s$(bc <<< ${MPOINTX_nmi}*${coeff})e9 s$(bc <<< ${MPOINTY_nmi}*${coeff})e9 \
|
||||
-d $bbb \
|
||||
-t 1e12 \
|
||||
-T 0.3 \
|
||||
-c 250 \
|
||||
-P
|
||||
done
|
||||
done
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
for bbb in 1 -2 2 -3 ; do
|
||||
for coeff in $(seq -0.200 0.010 0.200 | sed -e s/,/./g) ; do
|
||||
${MISCDIR}/lat2d_modes.py \
|
||||
-n $BG_REFINDEX \
|
||||
-b s${A1X_nm}e-9 s${A1Y_nm}e-9 \
|
||||
-b s${A2X_nm}e-9 s${A2Y_nm}e-9 \
|
||||
-p s${P1X_nm}e-9 s${P1Y_nm}e-9 \
|
||||
-L 3 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
-k s$(bc <<< ${B1X_nmi}*${coeff})e9 s$(bc <<< ${B1Y_nmi}*${coeff})e9 \
|
||||
-d $bbb \
|
||||
-T 0.2 \
|
||||
-c 250
|
||||
done
|
||||
done
|
||||
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
../modes/00_params.sh
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
for PSI in 0 1; do
|
||||
${MISCDIR}/infiniterectlat-scatter.py \
|
||||
-B $BG_REFINDEX \
|
||||
-p ${PX_nm}e-9 ${PY_nm}e-9 \
|
||||
-L 3 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
--theta "s-0.015:0.015|201" \
|
||||
--phi 0 \
|
||||
--psi $PSI \
|
||||
--chi 0 \
|
||||
-f "s2.110:2.230|100" \
|
||||
-P
|
||||
done
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
for PSI in 1; do
|
||||
${MISCDIR}/finiterectlat-scatter.py \
|
||||
--size 5 5\
|
||||
-B $BG_REFINDEX \
|
||||
-p ${PX_nm}e-9 ${PY_nm}e-9 \
|
||||
-L 2 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
--theta "s-0.05:0.05|101" \
|
||||
--phi 0 \
|
||||
--psi $PSI \
|
||||
--chi 0 \
|
||||
-f 2.15
|
||||
done
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
for PSI in 0 1; do
|
||||
${MISCDIR}/infiniterectlat-scatter.py \
|
||||
-B $BG_REFINDEX \
|
||||
-p ${PX_nm}e-9 ${PY_nm}e-9 \
|
||||
-L 2 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
--theta "s-0.05:0.05|101" \
|
||||
--phi 0 \
|
||||
--psi $PSI \
|
||||
--chi 0 \
|
||||
-P \
|
||||
-f 2.15
|
||||
done
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
##SBATCH --mem=50000
|
||||
##SBATCH -c 12
|
||||
##SBATCH -t 14:00:00
|
||||
##SBATCH -p batch
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
for PSI in 0 1; do
|
||||
${MISCDIR}/finiterectlat-scatter.py \
|
||||
--size 140 100 \
|
||||
-B $BG_REFINDEX \
|
||||
-p ${PX_nm}e-9 ${PY_nm}e-9 \
|
||||
-L 2 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
--theta "s-0.05:0.05|101" \
|
||||
--phi 0 \
|
||||
--psi $PSI \
|
||||
--chi 0 \
|
||||
-o 140x100.npz -O 140x100.pdf \
|
||||
-P \
|
||||
-f 2.15
|
||||
done
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
##SBATCH --mem=30000
|
||||
##SBATCH -c 12
|
||||
##SBATCH -t 14:00:00
|
||||
##SBATCH -p batch
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
for PSI in 1; do
|
||||
${MISCDIR}/finiterectlat-scatter.py \
|
||||
--size 100 100 \
|
||||
-B $BG_REFINDEX \
|
||||
-p ${PX_nm}e-9 ${PY_nm}e-9 \
|
||||
-L 2 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
--theta "s-0.05:0.05|101" \
|
||||
--phi 0 \
|
||||
--psi $PSI \
|
||||
--chi 0 \
|
||||
-o 100x100.npz -O 100x100.pdf \
|
||||
-P \
|
||||
-f 2.15
|
||||
done
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
##SBATCH --mem=50000
|
||||
##SBATCH -c 12
|
||||
##SBATCH -t 14:00:00
|
||||
##SBATCH -p batch
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
for PSI in 0 1; do
|
||||
${MISCDIR}/finiterectlat-scatter.py \
|
||||
--size 140 140 \
|
||||
-B $BG_REFINDEX \
|
||||
-p ${PX_nm}e-9 ${PY_nm}e-9 \
|
||||
-L 2 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
--theta "s-0.05:0.05|101" \
|
||||
--phi 0 \
|
||||
--psi $PSI \
|
||||
--chi 0 \
|
||||
-o 140x140.npz -O 140x140.pdf \
|
||||
-P \
|
||||
-f 2.15
|
||||
done
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
MISCDIR=../../../misc
|
||||
|
||||
source ${SCRIPTDIR}/00_params.sh
|
||||
|
||||
for PSI in 1; do
|
||||
${MISCDIR}/finiterectlat-scatter.py \
|
||||
--size 20 20 \
|
||||
-B $BG_REFINDEX \
|
||||
-p ${PX_nm}e-9 ${PY_nm}e-9 \
|
||||
-L 3 -m $METAL -r ${RADIUS_nm}e-9 -H ${HEIGHT_nm}e-9 \
|
||||
--theta "s-0.005:0.005|101" \
|
||||
--phi 0 \
|
||||
--psi $PSI \
|
||||
--chi 0 \
|
||||
-P \
|
||||
-f "s2.150:2.180|100" \
|
||||
|
||||
done
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,19 @@
|
|||
#!/bin/bash
|
||||
#SBATCH --mem=200
|
||||
#SBATCH -t 30:00
|
||||
#SBATCH -c 4
|
||||
#SBATCH -p short-ivb
|
||||
#SBATCH --array=0-250
|
||||
|
||||
cat $0
|
||||
|
||||
contour_points=410
|
||||
|
||||
#radii_nm=(`seq 80 1 150`)
|
||||
radii_nm=(`seq 50 1 300`)
|
||||
radius_nm=${radii_nm[$SLURM_ARRAY_TASK_ID]}
|
||||
|
||||
for lMax in $(seq 1 5); do
|
||||
srun rectlat_simple_modes.py -p 580e-9 -m '4+0.7j' -r ${radius_nm}e-9 -k 0 0 --kpi -n 1.52 -L lMax -t 1e11 -b -2 -f 0.1 -i 1. -T .3 -N ${contour_points}
|
||||
done
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
|
||||
kx=0.0
|
||||
contour_points=410
|
||||
|
||||
radii_nm=(`seq 50 1 300`)
|
||||
radius_nm=${radii_nm[$SLURM_ARRAY_TASK_ID]}
|
||||
|
||||
for lMax in $(seq 1 5) ; do
|
||||
for radius_nm in $(seq 50 1 300) ; do
|
||||
rectlat_simple_modes.py -p 580e-9 -m 'Au' -r ${radius_nm}e-9 -k $kx 0 --kpi -n 1.52 -L $lMax -t 1e11 -b -2 -f 0.1 -i 1. -T .3 -N ${contour_points} --lMax-extend 10
|
||||
done
|
||||
done
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
kx=0.0
|
||||
contour_points=410
|
||||
|
||||
radii_nm=(`seq 50 1 300`)
|
||||
radius_nm=${radii_nm[$SLURM_ARRAY_TASK_ID]}
|
||||
|
||||
for radius_nm in $(seq 50 1 300) ; do
|
||||
rectlat_simple_modes.py -p 580e-9 -m 'Au' -r ${radius_nm}e-9 -k $kx 0 --kpi -n 1.52 -L 1 -t 1e11 -b -2 -f 0.1 -i 1. -T .3 -N ${contour_points}
|
||||
done
|
|
@ -0,0 +1,300 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%matplotlib inline\n",
|
||||
"import re\n",
|
||||
"import numpy as np\n",
|
||||
"import matplotlib\n",
|
||||
"from matplotlib import pyplot as plt\n",
|
||||
"from scipy.constants import hbar, e as eV, c\n",
|
||||
"eh = eV/hbar\n",
|
||||
"import glob\n",
|
||||
"def ri(z): return (z.real, z.imag)\n",
|
||||
"#m = re.compile(r\"([^_]+)_r([0-9.]+)nm_\")\n",
|
||||
"#removek = re.compile(r\"(k\\([^)]+\\)um-1_)\")\n",
|
||||
"remover = re.compile(r\"r[0-9.]+nm_\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"markerdict = {\n",
|
||||
" 4: \"3\",\n",
|
||||
" -4: \"4\",\n",
|
||||
" 3: \"^\",\n",
|
||||
" -3: \"v\",\n",
|
||||
" -2: 'x',\n",
|
||||
" 2: '+',\n",
|
||||
" 1: 's',\n",
|
||||
" -1: 'd',\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"prop_cycle = plt.rcParams['axes.prop_cycle']\n",
|
||||
"colors = prop_cycle.by_key()['color']\n",
|
||||
"colordict = {i: colors[(i+1)] for i in range(-4,8)}\n",
|
||||
"\n",
|
||||
"def markerfun(b):\n",
|
||||
" if b in markerdict.keys():\n",
|
||||
" return markerdict[b]\n",
|
||||
" else: return 'X'\n",
|
||||
"\n",
|
||||
"def colorfun(b):\n",
|
||||
" if (b+1) in colordict.keys():\n",
|
||||
" return colordict[b+1]\n",
|
||||
" else: return colordict[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"allfiles=glob.glob('*sph*k(0_0)*.npz')\n",
|
||||
"allgraphs=dict()\n",
|
||||
"for f in allfiles:\n",
|
||||
" base = remover.sub('', f)\n",
|
||||
" if base in allgraphs.keys():\n",
|
||||
" allgraphs[base] += 1\n",
|
||||
" else:\n",
|
||||
" allgraphs[base] = 1\n",
|
||||
"for k in sorted(allgraphs.keys()):\n",
|
||||
" print(k, allgraphs[k])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "FileNotFoundError",
|
||||
"evalue": "[Errno 2] No such file or directory: 'projectors_D4h_lMax1.npz'",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
||||
"\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)",
|
||||
"\u001b[0;32m<ipython-input-3-0c266089be08>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mlMaxes\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mlMax\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mlMax\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m6\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mlMax\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mlMaxes\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mproj\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mload\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'projectors_D4h_lMax%d.npz'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mlMax\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m \u001b[0mirlabels\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msorted\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mproj\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0mproj\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mproj\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mf\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mirlabels\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
||||
"\u001b[0;32m~/.local/lib/python3.7/site-packages/numpy-1.17.3-py3.7-linux-x86_64.egg/numpy/lib/npyio.py\u001b[0m in \u001b[0;36mload\u001b[0;34m(file, mmap_mode, allow_pickle, fix_imports, encoding)\u001b[0m\n\u001b[1;32m 426\u001b[0m \u001b[0mown_fid\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 427\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 428\u001b[0;31m \u001b[0mfid\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mopen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mos_fspath\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfile\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"rb\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 429\u001b[0m \u001b[0mown_fid\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 430\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
|
||||
"\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'projectors_D4h_lMax1.npz'"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"projectors = dict()\n",
|
||||
"projectors_list = dict()\n",
|
||||
"lMaxes = [lMax for lMax in range(1,6)]\n",
|
||||
"for lMax in lMaxes:\n",
|
||||
" proj = np.load('projectors_D4h_lMax%d.npz' % lMax)\n",
|
||||
" irlabels = sorted(proj.keys())\n",
|
||||
" proj = {f: proj[f] for f in irlabels}\n",
|
||||
" proj_list = [proj[irlabels[i]] for i in range(len(proj))]\n",
|
||||
" projectors[lMax] = proj\n",
|
||||
" projectors_list[lMax] = proj_list\n",
|
||||
"globpattern = '*sph_r*_p580nmx580nm_mAu_n1.52_b?2_k(0_0)um-1_L?_cn???.npz'\n",
|
||||
"filenames=glob.glob(globpattern)\n",
|
||||
"plotfilename = 'collected_' + globpattern.replace('*', 'XXX').replace('?', 'X').replace('npz','pdf')\n",
|
||||
"print(filenames[:4], plotfilename)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 41,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#projectors\n",
|
||||
"#glob.glob('cyl_r100nm*L3*3100.npz')\n",
|
||||
"#glob.glob('sph_r100*m5*.npz')\n",
|
||||
"#dat['meta'][()],list(dat.keys())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 42,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"inpure result detected [1. 0.99999999 1. 0.97991334 0.99999996 0.9999989\n",
|
||||
" 0.99999983 0.99999966 0.99999322 0.99999721 0.99999653] [3.28735741e-04 2.66532534e-05 2.47011478e-05 1.45012420e-01\n",
|
||||
" 2.44785416e-04 7.05405359e-04 1.60203586e-03 1.71245137e-03\n",
|
||||
" 1.03244480e-02 9.18732728e-03 1.18651583e-02]\n",
|
||||
"inpure result detected [1. 1. 0.99999998 0.99999999 0.99999996 0.96608887\n",
|
||||
" 0.99999852 0.99999397 0.99998951 0.99999912 0.99982435] [2.66223026e-04 2.12357147e-05 3.54211968e-05 1.06651057e-04\n",
|
||||
" 2.79595790e-04 2.41939163e-01 2.17645058e-03 3.41541473e-03\n",
|
||||
" 1.14507609e-02 1.49639498e-02 2.33483138e-02]\n",
|
||||
"inpure result detected [1. 1. 0.92521572 1. 0.99999627 0.99990293\n",
|
||||
" 0.99946049] [1.59712906e-05 3.60193407e-05 2.48341492e-01 1.21848930e-03\n",
|
||||
" 3.81805601e-03 2.42649228e-02 2.99534246e-02]\n",
|
||||
"inpure result detected [1. 1. 0.99999998 0.99999961 0.93267685 0.99999964\n",
|
||||
" 0.99999822 0.99921774 0.99995547 0.99997301] [5.22490396e-04 3.01556792e-05 4.88795563e-05 6.29703960e-04\n",
|
||||
" 2.34414238e-01 3.72766210e-03 4.72444059e-03 7.62106094e-02\n",
|
||||
" 6.32796684e-02 5.63231562e-02]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"plotdata = {}\n",
|
||||
"for file in filenames:\n",
|
||||
" dat = np.load(file, allow_pickle=True)\n",
|
||||
" kx = dat['meta'][()]['k'][0]\n",
|
||||
" radius = dat['meta'][()]['radius']\n",
|
||||
" b = dat['meta'][()]['band_index']\n",
|
||||
" eigvals = dat['eigval']\n",
|
||||
" lMax = dat['meta'][()]['lMax']\n",
|
||||
" residuals = dat['residuals']\n",
|
||||
" ef =dat['empty_freqs']\n",
|
||||
" eigvecs = dat['eigvec']\n",
|
||||
" irweights = []\n",
|
||||
" #for proj in projectors_list[lMax]:\n",
|
||||
" # try:\n",
|
||||
" # irweights.append(np.linalg.norm(np.tensordot(proj, eigvecs, axes=(-1, -1)), axis=0,ord=2) if len(proj) != 0 else np.zeros((len(eigvecs),)))\n",
|
||||
" # except ValueError as err:\n",
|
||||
" # print(proj, len(proj))\n",
|
||||
" # raise err\n",
|
||||
" irweights = np.array(irweights)\n",
|
||||
" #print(irweights)\n",
|
||||
" irweights = np.array([np.linalg.norm(np.tensordot(proj, eigvecs, axes=(-1, -1)), axis=0,ord=2) if len(proj) != 0 else np.zeros((len(eigvecs),)) for proj in projectors_list[lMax]]).T\n",
|
||||
" irclass = np.argmax(irweights, axis=-1)\n",
|
||||
" purities = np.amax(irweights, axis=-1)\n",
|
||||
" if (np.any(purities < 0.98)):\n",
|
||||
" print(\"inpure result detected\", purities, residuals)\n",
|
||||
" #print(purities)\n",
|
||||
" \n",
|
||||
" #for i in range(len(residuals)): \n",
|
||||
" # if residuals[i] < 0.01:\n",
|
||||
" # vec = eigvecs[i]\n",
|
||||
" # for irlabel, proj in projectors.items():\n",
|
||||
" # print(irlabel, np.linalg.norm(np.dot(proj, vec))) #maybe some conj() here?\n",
|
||||
" # print('--->', irlabels[irclass[i]])\n",
|
||||
"\n",
|
||||
" \n",
|
||||
" plotdata[(lMax,radius)] = (eigvals, residuals, b, ef, irclass,)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fig = plt.figure(figsize=(15,6))\n",
|
||||
"axesR = {}\n",
|
||||
"axesI = {}\n",
|
||||
"for i, lMax in enumerate(lMaxes):\n",
|
||||
" axesR[lMax] = fig.add_subplot(2,len(lMaxes),i+1)\n",
|
||||
" axesR[lMax].set_xlim([50,300])\n",
|
||||
" axesR[lMax].set_ylim([1.25, ef[1]/eh])\n",
|
||||
" axesI[lMax] = fig.add_subplot(2,len(lMaxes),len(lMaxes)+i+1)\n",
|
||||
" axesI[lMax].set_xlim([50,300])\n",
|
||||
" axesI[lMax].set_ylim([-60, 30])\n",
|
||||
" axesR[lMax].set_title('$l_\\max = %d $' % lMax) \n",
|
||||
" axesR[lMax].tick_params(labelbottom=False) \n",
|
||||
" if i == len(lMaxes)//2:\n",
|
||||
" axesI[lMax].set_xlabel(\"Particle base radius / nm\")\n",
|
||||
" if i == 0:\n",
|
||||
" axesR[lMax].set_ylabel('$\\hbar \\Re \\omega / \\mathrm{eV}$')\n",
|
||||
" axesI[lMax].set_ylabel('$\\hbar \\Im \\omega / \\mathrm{meV}$')\n",
|
||||
" else:\n",
|
||||
" axesR[lMax].tick_params(labelleft=False) \n",
|
||||
" axesI[lMax].tick_params(labelleft=False) \n",
|
||||
"\n",
|
||||
"res_thr = 0.005\n",
|
||||
"\n",
|
||||
"ir_labeled=set()\n",
|
||||
"if True:\n",
|
||||
" for (lMax, radius), (eigvals, residuals, b, ef, irclass) in plotdata.items():\n",
|
||||
" for i, (e, res, iri) in enumerate(zip(eigvals, residuals, irclass)):\n",
|
||||
" #if i == 0:\n",
|
||||
" if res < res_thr:# and e.real < 2.14e15:\n",
|
||||
" if iri in ir_labeled: \n",
|
||||
" label=None\n",
|
||||
" else:\n",
|
||||
" ir_labeled.add(iri)\n",
|
||||
" label=irlabels[iri]\n",
|
||||
" axesR[lMax].plot(radius*1e9, e.real/eh, \n",
|
||||
" marker='.',\n",
|
||||
" #marker=markerfun(b),\n",
|
||||
" ms=4, #c=colorfun(b)\n",
|
||||
" c=matplotlib.cm.hsv(iri/9),\n",
|
||||
" #c = colorfun(iri),\n",
|
||||
" label=label,\n",
|
||||
" )\n",
|
||||
" axesI[lMax].plot(radius*1e9, e.imag/eh*1000, \n",
|
||||
" #marker='x', \n",
|
||||
" #c=colorfun(b), \n",
|
||||
" c=matplotlib.cm.hsv(iri/9),#colorfun(iri),\n",
|
||||
" marker='.', #markerfun(b),\n",
|
||||
" ms=4,\n",
|
||||
" #label=label\n",
|
||||
" )\n",
|
||||
"fig.legend(title=\"Irrep\", loc=\"center right\")\n",
|
||||
"#fig.suptitle('$l_\\mathrm{max}=%d$, residual threshold = %g' % (lMax, res_thr) )\n",
|
||||
"fig.savefig(plotfilename)\n",
|
||||
"fig.savefig(plotfilename.replace('pdf', 'png'))\n",
|
||||
"print(plotfilename)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 55,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([0. , 1.40635433, 1.98888536, 2.81270865, 3.14470387,\n",
|
||||
" 3.97777072, 4.21906298, 4.44728287])"
|
||||
]
|
||||
},
|
||||
"execution_count": 55,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"ef / eh"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.7.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
cmake_minimum_required(VERSION 3.0)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
project(Faddeeva VERSION 1.0 LANGUAGES C)
|
||||
|
||||
option(FADDEEVA_BUILD_STATIC "Build Faddeeva as static library" OFF)
|
||||
|
||||
if (FADDEEVA_BUILD_STATIC)
|
||||
add_library(Faddeeva STATIC Faddeeva.h Faddeeva.c Faddeeva.cc)
|
||||
else (FADDEEVA_BUILD_STATIC)
|
||||
add_library(Faddeeva SHARED Faddeeva.c)
|
||||
set_target_properties(Faddeeva PROPERTIES PUBLIC_HEADER "Faddeeva.h")
|
||||
install(TARGETS Faddeeva
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
endif (FADDEEVA_BUILD_STATIC)
|
||||
target_include_directories(Faddeeva PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
/* The Faddeeva.cc file contains macros to let it compile as C code
|
||||
(assuming C99 complex-number support), so just #include it. */
|
||||
#include "Faddeeva.cc"
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,68 @@
|
|||
/* Copyright (c) 2012 Massachusetts Institute of Technology
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Available at: http://ab-initio.mit.edu/Faddeeva
|
||||
|
||||
Header file for Faddeeva.c; see Faddeeva.cc for more information. */
|
||||
|
||||
#ifndef FADDEEVA_H
|
||||
#define FADDEEVA_H 1
|
||||
|
||||
// Require C99 complex-number support
|
||||
#include <complex.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
// compute w(z) = exp(-z^2) erfc(-iz) [ Faddeeva / scaled complex error func ]
|
||||
extern double complex Faddeeva_w(double complex z,double relerr);
|
||||
extern double Faddeeva_w_im(double x); // special-case code for Im[w(x)] of real x
|
||||
|
||||
// Various functions that we can compute with the help of w(z)
|
||||
|
||||
// compute erfcx(z) = exp(z^2) erfc(z)
|
||||
extern double complex Faddeeva_erfcx(double complex z, double relerr);
|
||||
extern double Faddeeva_erfcx_re(double x); // special case for real x
|
||||
|
||||
// compute erf(z), the error function of complex arguments
|
||||
extern double complex Faddeeva_erf(double complex z, double relerr);
|
||||
extern double Faddeeva_erf_re(double x); // special case for real x
|
||||
|
||||
// compute erfi(z) = -i erf(iz), the imaginary error function
|
||||
extern double complex Faddeeva_erfi(double complex z, double relerr);
|
||||
extern double Faddeeva_erfi_re(double x); // special case for real x
|
||||
|
||||
// compute erfc(z) = 1 - erf(z), the complementary error function
|
||||
extern double complex Faddeeva_erfc(double complex z, double relerr);
|
||||
extern double Faddeeva_erfc_re(double x); // special case for real x
|
||||
|
||||
// compute Dawson(z) = sqrt(pi)/2 * exp(-z^2) * erfi(z)
|
||||
extern double complex Faddeeva_Dawson(double complex z, double relerr);
|
||||
extern double Faddeeva_Dawson_re(double x); // special case for real x
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif // FADDEEVA_H
|
|
@ -0,0 +1,62 @@
|
|||
/* Copyright (c) 2012 Massachusetts Institute of Technology
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Available at: http://ab-initio.mit.edu/Faddeeva
|
||||
|
||||
Header file for Faddeeva.cc; see that file for more information. */
|
||||
|
||||
#ifndef FADDEEVA_HH
|
||||
#define FADDEEVA_HH 1
|
||||
|
||||
#include <complex>
|
||||
|
||||
namespace Faddeeva {
|
||||
|
||||
// compute w(z) = exp(-z^2) erfc(-iz) [ Faddeeva / scaled complex error func ]
|
||||
extern std::complex<double> w(std::complex<double> z,double relerr=0);
|
||||
extern double w_im(double x); // special-case code for Im[w(x)] of real x
|
||||
|
||||
// Various functions that we can compute with the help of w(z)
|
||||
|
||||
// compute erfcx(z) = exp(z^2) erfc(z)
|
||||
extern std::complex<double> erfcx(std::complex<double> z, double relerr=0);
|
||||
extern double erfcx(double x); // special case for real x
|
||||
|
||||
// compute erf(z), the error function of complex arguments
|
||||
extern std::complex<double> erf(std::complex<double> z, double relerr=0);
|
||||
extern double erf(double x); // special case for real x
|
||||
|
||||
// compute erfi(z) = -i erf(iz), the imaginary error function
|
||||
extern std::complex<double> erfi(std::complex<double> z, double relerr=0);
|
||||
extern double erfi(double x); // special case for real x
|
||||
|
||||
// compute erfc(z) = 1 - erf(z), the complementary error function
|
||||
extern std::complex<double> erfc(std::complex<double> z, double relerr=0);
|
||||
extern double erfc(double x); // special case for real x
|
||||
|
||||
// compute Dawson(z) = sqrt(pi)/2 * exp(-z^2) * erfi(z)
|
||||
extern std::complex<double> Dawson(std::complex<double> z, double relerr=0);
|
||||
extern double Dawson(double x); // special case for real x
|
||||
|
||||
} // namespace Faddeeva
|
||||
|
||||
#endif // FADDEEVA_HH
|
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
|
@ -1,6 +1,8 @@
|
|||
Using QPMS library for simulating finite systems
|
||||
================================================
|
||||
|
||||
*** This tutorial is partly obsolete, the interpolators are no longer the first choice of getting the T-matrices. ***
|
||||
|
||||
The main C API for finite systems is defined in [scatsystem.h][], and the
|
||||
most relevant parts are wrapped into python modules. The central data structure
|
||||
defining the system of scatterers is [qpms_scatsys_t][],
|
||||
|
|
118
lattices.md
118
lattices.md
|
@ -1,118 +0,0 @@
|
|||
Using QPMS library for finding modes of 2D-periodic systems
|
||||
===========================================================
|
||||
|
||||
Calculating modes of infinite 2D arrays is now done
|
||||
in several steps (assuming the T-matrices have already
|
||||
been obtained using `scuff-tmatrix` or can be obtained
|
||||
from Lorenz-Mie solution (spherical particles)):
|
||||
|
||||
1. Sampling the *k*, *ω* space.
|
||||
2. Pre-calculating the
|
||||
Ewald-summed translation operators.
|
||||
3. For each *k*, *ω* pair, build the LHS operator
|
||||
for the scattering problem (TODO reference), optionally decomposed
|
||||
into suitable irreducible representation subspaces.
|
||||
4. Evaluating the singular values and finding their minima.
|
||||
|
||||
The steps above may (and will) change as more user-friendly interface
|
||||
will be developed.
|
||||
|
||||
|
||||
Preparation: compile the `ew_gen_kin` utility
|
||||
---------------------------------------------
|
||||
|
||||
This will change, but at this point, the lattice-summed
|
||||
translation operators are computed using the `ew_gen_kin`
|
||||
utility located in the `qpms/apps` directory. It has to be built
|
||||
manually like this:
|
||||
|
||||
```bash
|
||||
cd qpms/apps
|
||||
c99 -o ew_gen_kin -Wall -I ../.. -I ../../amos/ -O2 -ggdb -DQPMS_VECTORS_NICE_TRANSFORMATIONS -DLATTICESUMS32 2dlattice_ewald.c ../translations.c ../ewald.c ../ewaldsf.c ../gaunt.c ../lattices2d.c ../latticegens.c ../bessel.c -lgsl -lm -lblas ../../amos/libamos.a -lgfortran ../error.c
|
||||
```
|
||||
|
||||
Step 1: Sampling the *k*, *ω* space
|
||||
--------------------------------------
|
||||
|
||||
`ew_gen_kin` expects a list of (*k_x*, *k_y*)
|
||||
pairs on standard input (separated by whitespaces),
|
||||
the rest is specified via command line arguments.
|
||||
|
||||
So if we want to examine the line between the Г point and the point
|
||||
\f$ k = (0, 10^5\,\mathrm{m}^{-1}) \f$, we can generate an input
|
||||
running
|
||||
```bash
|
||||
for ky in $(seq 0 1e3 1e5); do
|
||||
echo 0 $ky >> klist
|
||||
done
|
||||
```
|
||||
|
||||
It also make sense to pre-generate the list of *ω* values,
|
||||
e.g.
|
||||
```bash
|
||||
seq 6.900 0.002 7.3 | sed -e 's/,/./g' > omegalist
|
||||
```
|
||||
|
||||
|
||||
Step 2: Pre-calculating the translation operators
|
||||
-------------------------------------------------
|
||||
|
||||
`ew_gen_kin` currently uses command-line arguments in
|
||||
an atrocious way with a hard-coded order:
|
||||
```
|
||||
ew_gen_kin outfile b1.x b1.y b2.x b2.y lMax scuffomega refindex npart part0.x part0.y [part1.x part1.y [...]]
|
||||
```
|
||||
where `outfile` specifies the path to the output, `b1` and `b2` are the
|
||||
direct lattice vectors, `lMax` is the multipole degree cutoff,
|
||||
`scuffomega` is the frequency in the units used by `scuff-tmatrix`
|
||||
(TODO specify), `refindex` is the refractive index of the background
|
||||
medium, `npart` number of particles in the unit cell, and `partN` are
|
||||
the positions of these particles inside the unit cell.
|
||||
|
||||
Assuming we have the `ew_gen_kin` binary in our `${PATH}`, we can
|
||||
now run e.g.
|
||||
```bash
|
||||
for omega in $(cat omegalist); do
|
||||
ew_gen_kin $omega 621e-9 0 0 571e-9 3 w_$omega 1.52 1 0 0 < klist
|
||||
done
|
||||
```
|
||||
This pre-calculates the translation operators for a simple (one particle per unit cell)
|
||||
621 nm × 571 nm rectangular lattice inside a medium with refractive index 1.52,
|
||||
up to the octupole (`lMax` = 3) order, yielding one file per frequency.
|
||||
This can take some time and
|
||||
it makes sense to run a parallelised `for`-loop instead; this is a stupid but working
|
||||
way to do it in bash:
|
||||
```bash
|
||||
N=4 # number of parallel processes
|
||||
for omega in $(cat omegalist); do
|
||||
((i=i%N)); ((i++==0)) && wait
|
||||
ew_gen_kin $omega 621e-9 0 0 571e-9 3 w_$omega 1.52 1 0 0 < klist
|
||||
echo $omega # optional, to follow progress
|
||||
done
|
||||
```
|
||||
|
||||
When this is done, we convert all the text output files into
|
||||
numpy's binary format in order to speed up loading in the following steps.
|
||||
This is done using the processWfiles_sortnames.py script located in the
|
||||
`misc` directory. Its usage pattern is
|
||||
```
|
||||
processWfiles_sortnames.py npart dest src1 [src2 ...]
|
||||
```
|
||||
where `npart` is the number of particles in the unit cell, `dest`
|
||||
is the destination path for the converted data (this will be
|
||||
a directory), and the remaining arguments are paths to the
|
||||
files generated by `ew_gen_kin`. In the case above, one could use
|
||||
```
|
||||
processWfiles_sortnames.py 1 all w_*
|
||||
```
|
||||
which would create a directory named `all` containing several
|
||||
.npy files.
|
||||
|
||||
|
||||
Steps 3, 4
|
||||
----------
|
||||
|
||||
TODO. For the time being, see e.g. the `SaraRect/dispersions.ipynb` jupyter notebook
|
||||
from the `qpms_ipynotebooks` repository
|
||||
for the remaining steps.
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# coding: utf-8
|
||||
from qpms import Particle, CTMatrix, BaseSpec, FinitePointGroup, ScatteringSystem, TMatrixInterpolator, eV, hbar, c, MaterialInterpolator, scatsystem_set_nthreads
|
||||
from qpms.symmetries import point_group_info
|
||||
import numpy as np
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
if 'SLURM_CPUS_PER_TASK' in os.environ:
|
||||
scatsystem_set_nthreads(int(os.environ['SLURM_CPUS_PER_TASK']))
|
||||
nm = 1e-9
|
||||
|
||||
rewrite_output = '--rewrite-output' in sys.argv
|
||||
|
||||
sym = FinitePointGroup(point_group_info['D2h'])
|
||||
bspec = BaseSpec(lMax = 2)
|
||||
tmfile = '/m/phys/project/qd/Marek/tmatrix-experiments/Cylinder/AaroBEC/cylinder_50nm_lMax4_longer.TMatrix'
|
||||
#outputdatadir = '/home/necadam1/wrkdir/AaroBECfinite_new'
|
||||
outputdatadir = '/u/46/necadam1/unix/project/AaroBECfinite_new'
|
||||
os.makedirs(outputdatadir, exist_ok = True)
|
||||
interp = TMatrixInterpolator(tmfile, bspec, symmetrise = sym, atol = 1e-8)
|
||||
# There is only one t-matrix in the system for each frequency. We initialize the matrix with the lowest frequency data.
|
||||
# Later, we can replace it using the tmatrix[...] = interp(freq) and s.update_tmatrices NOT YET; TODO
|
||||
|
||||
omega = float(sys.argv[3]) * eV/hbar
|
||||
sv_threshold = float(sys.argv[4])
|
||||
|
||||
# Now place the particles and set background index.
|
||||
px = 571*nm; py = 621*nm
|
||||
n = 1.52
|
||||
Nx = int(sys.argv[1])
|
||||
Ny = int(sys.argv[2])
|
||||
|
||||
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
|
||||
|
||||
orig_xy = np.stack(np.meshgrid(orig_x, orig_y), axis = -1)
|
||||
|
||||
tmatrix = interp(omega)
|
||||
#print(tmatrix.m)
|
||||
|
||||
particles = [Particle(orig_xy[i], tmatrix) for i in np.ndindex(orig_xy.shape[:-1])]
|
||||
|
||||
ss = ScatteringSystem(particles, sym)
|
||||
|
||||
k = n * omega / c
|
||||
|
||||
for iri in range(ss.nirreps):
|
||||
destpath = os.path.join(outputdatadir, 'Nx%d_Ny%d_%geV_ir%d.npz'%(Nx, Ny, omega/eV*hbar, iri,))
|
||||
touchpath = os.path.join(outputdatadir, 'Nx%d_Ny%d_%geV_ir%d.done'%(Nx, Ny, omega/eV*hbar, iri,))
|
||||
if (os.path.isfile(destpath) or os.path.isfile(touchpath)) and not rewrite_output:
|
||||
print(destpath, 'already exists, skipping')
|
||||
continue
|
||||
mm_iri = ss.modeproblem_matrix_packed(k, iri)
|
||||
#print(mm_iri)
|
||||
U, S, Vh = np.linalg.svd(mm_iri)
|
||||
del U
|
||||
print(iri, ss.irrep_names[iri], S[-1])
|
||||
starti = max(0,len(S) - np.searchsorted(S[::-1], sv_threshold, side='left')-1)
|
||||
np.savez(destpath,
|
||||
S=S[starti:], omega=omega, Vh = Vh[starti:], iri=iri, Nx = Nx, Ny= Ny )
|
||||
del S
|
||||
del Vh
|
||||
Path(touchpath).touch()
|
||||
# Don't forget to conjugate Vh before transforming it to the full vector!
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# coding: utf-8
|
||||
from qpms import Particle, CTMatrix, BaseSpec, FinitePointGroup, ScatteringSystem, TMatrixInterpolator, eV, hbar, c, MaterialInterpolator, scatsystem_set_nthreads
|
||||
from qpms.symmetries import point_group_info
|
||||
from pathlib import Path
|
||||
import numpy as np
|
||||
import os
|
||||
import sys
|
||||
nm = 1e-9
|
||||
|
||||
|
||||
if 'SLURM_CPUS_PER_TASK' in os.environ:
|
||||
scatsystem_set_nthreads(int(os.environ['SLURM_CPUS_PER_TASK']))
|
||||
|
||||
|
||||
rewrite_output = '--rewrite-output' in sys.argv
|
||||
|
||||
cyr_part_height = 50*nm
|
||||
cyr_part_radius = 50*nm
|
||||
cyr_part_volume = cyr_part_height * np.pi * cyr_part_radius**2
|
||||
eqv_sph_radius = (3/4/np.pi*cyr_part_volume)**(1/3)
|
||||
|
||||
sym = FinitePointGroup(point_group_info['D2h'])
|
||||
bspec = BaseSpec(lMax = 2)
|
||||
#tmfile = '/m/phys/project/qd/Marek/tmatrix-experiments/Cylinder/AaroBEC/cylinder_50nm_lMax4_cleaned.TMatrix'
|
||||
materialfile = '/home/necadam1/wrkdir/repo/refractiveindex.info-database/database/data/main/Au/Johnson.yml'
|
||||
|
||||
#outputdatadir = '/home/necadam1/wrkdir/AaroBECfinite_new'
|
||||
#outputdatadir = '/u/46/necadam1/unix/project/AaroBECfinite_sph'
|
||||
outputdatadir = '/home/necadam1/wrkdir/AaroBECfinite_sph'
|
||||
os.makedirs(outputdatadir, exist_ok = True)
|
||||
mi = MaterialInterpolator(materialfile)
|
||||
#interp = TMatrixInterpolator(tmfile, bspec, symmetrise = sym, atol = 1e-8)
|
||||
# There is only one t-matrix in the system for each frequency. We initialize the matrix with the lowest frequency data.
|
||||
# Later, we can replace it using the tmatrix[...] = interp(freq) and s.update_tmatrices NOT YET; TODO
|
||||
|
||||
omega = float(sys.argv[3]) * eV/hbar
|
||||
sv_threshold = float(sys.argv[4])
|
||||
|
||||
# Now place the particles and set background index.
|
||||
px = 571*nm; py = 621*nm
|
||||
n = 1.52
|
||||
Nx = int(sys.argv[1])
|
||||
Ny = int(sys.argv[2])
|
||||
|
||||
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
|
||||
|
||||
orig_xy = np.stack(np.meshgrid(orig_x, orig_y), axis = -1)
|
||||
|
||||
#tmatrix = interp(omega)
|
||||
tmatrix = CTMatrix.spherical_perm(bspec, eqv_sph_radius, omega, mi(omega), n**2)
|
||||
particles = [Particle(orig_xy[i], tmatrix) for i in np.ndindex(orig_xy.shape[:-1])]
|
||||
|
||||
|
||||
ss = ScatteringSystem(particles, sym)
|
||||
|
||||
|
||||
k = n * omega / c
|
||||
|
||||
|
||||
for iri in range(ss.nirreps):
|
||||
destpath = os.path.join(outputdatadir, 'Nx%d_Ny%d_%geV_ir%d.npz'%(Nx, Ny, omega/eV*hbar, iri))
|
||||
touchpath = os.path.join(outputdatadir, 'Nx%d_Ny%d_%geV_ir%d.done'%(Nx, Ny, omega/eV*hbar, iri))
|
||||
if (os.path.isfile(destpath) or os.path.isfile(touchpath)) and not rewrite_output:
|
||||
print(destpath, 'already exists, skipping')
|
||||
continue
|
||||
mm_iri = ss.modeproblem_matrix_packed(k, iri)
|
||||
U, S, Vh = np.linalg.svd(mm_iri)
|
||||
del U
|
||||
print(iri, ss.irrep_names[iri], S[-1])
|
||||
starti = max(0,len(S) - np.searchsorted(S[::-1], sv_threshold, side='left')-1)
|
||||
np.savez(destpath,
|
||||
S=S[starti:], omega=omega, Vh = Vh[starti:], iri=iri, Nx = Nx, Ny= Ny )
|
||||
del S
|
||||
del Vh
|
||||
Path(touchpath).touch()
|
||||
# Don't forget to conjugate Vh before transforming it to the full vector!
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# coding: utf-8
|
||||
from qpms import Particle, CTMatrix, BaseSpec, FinitePointGroup, ScatteringSystem, TMatrixInterpolator, eV, hbar, c, MaterialInterpolator, scatsystem_set_nthreads
|
||||
from qpms.symmetries import point_group_info
|
||||
import numpy as np
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
if 'SLURM_CPUS_PER_TASK' in os.environ:
|
||||
scatsystem_set_nthreads(int(os.environ['SLURM_CPUS_PER_TASK']))
|
||||
|
||||
nm = 1e-9
|
||||
|
||||
rewrite_output = '--rewrite-output' in sys.argv
|
||||
|
||||
radiusfactor = float(sys.argv[5])
|
||||
|
||||
cyr_part_height = 50*nm
|
||||
cyr_part_radius = 50*nm
|
||||
cyr_part_volume = cyr_part_height * np.pi * cyr_part_radius**2
|
||||
eqv_sph_radius = (3/4/np.pi*cyr_part_volume)**(1/3) * radiusfactor
|
||||
|
||||
sym = FinitePointGroup(point_group_info['D2h'])
|
||||
bspec = BaseSpec(lMax = 2)
|
||||
#tmfile = '/m/phys/project/qd/Marek/tmatrix-experiments/Cylinder/AaroBEC/cylinder_50nm_lMax4_cleaned.TMatrix'
|
||||
materialfile = '/home/necadam1/wrkdir/repo/refractiveindex.info-database/database/data/main/Au/Johnson.yml'
|
||||
|
||||
#outputdatadir = '/home/necadam1/wrkdir/AaroBECfinite_new'
|
||||
#outputdatadir = '/u/46/necadam1/unix/project/AaroBECfinite_sph'
|
||||
outputdatadir = '/home/necadam1/wrkdir/AaroBECfinite_fatsph'
|
||||
os.makedirs(outputdatadir, exist_ok = True)
|
||||
mi = MaterialInterpolator(materialfile)
|
||||
#interp = TMatrixInterpolator(tmfile, bspec, symmetrise = sym, atol = 1e-8)
|
||||
# There is only one t-matrix in the system for each frequency. We initialize the matrix with the lowest frequency data.
|
||||
# Later, we can replace it using the tmatrix[...] = interp(freq) and s.update_tmatrices NOT YET; TODO
|
||||
|
||||
omega = float(sys.argv[3]) * eV/hbar
|
||||
sv_threshold = float(sys.argv[4])
|
||||
|
||||
|
||||
# Now place the particles and set background index.
|
||||
px = 571*nm; py = 621*nm
|
||||
n = 1.52
|
||||
Nx = int(sys.argv[1])
|
||||
Ny = int(sys.argv[2])
|
||||
|
||||
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
|
||||
|
||||
orig_xy = np.stack(np.meshgrid(orig_x, orig_y), axis = -1)
|
||||
|
||||
#tmatrix = interp(omega)
|
||||
tmatrix = CTMatrix.spherical_perm(bspec, eqv_sph_radius, omega, mi(omega), n**2)
|
||||
particles = [Particle(orig_xy[i], tmatrix) for i in np.ndindex(orig_xy.shape[:-1])]
|
||||
|
||||
|
||||
ss = ScatteringSystem(particles, sym)
|
||||
|
||||
|
||||
k = n * omega / c
|
||||
|
||||
|
||||
for iri in range(ss.nirreps):
|
||||
destpath = os.path.join(outputdatadir, 'Nx%d_Ny%d_%geV_ir%d_r%gnm.npz'%(Nx, Ny, omega/eV*hbar, iri, eqv_sph_radius/nm))
|
||||
touchpath = os.path.join(outputdatadir, 'Nx%d_Ny%d_%geV_ir%d_r%gnm.done'%(Nx, Ny, omega/eV*hbar, iri, eqv_sph_radius/nm))
|
||||
if (os.path.isfile(destpath) or os.path.isfile(touchpath)) and not rewrite_output:
|
||||
print(destpath, 'already exists, skipping')
|
||||
continue
|
||||
mm_iri = ss.modeproblem_matrix_packed(k, iri)
|
||||
U, S, Vh = np.linalg.svd(mm_iri)
|
||||
del U
|
||||
print(iri, ss.irrep_names[iri], S[-1])
|
||||
starti = max(0,len(S) - np.searchsorted(S[::-1], sv_threshold, side='left')-1)
|
||||
np.savez(destpath,
|
||||
S=S[starti:], omega=omega, Vh = Vh[starti:], iri=iri, Nx = Nx, Ny= Ny )
|
||||
del S
|
||||
del Vh
|
||||
Path(touchpath).touch()
|
||||
# Don't forget to conjugate Vh before transforming it to the full vector!
|
||||
|
|
@ -1,547 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
|
||||
import argparse, re, random, string
|
||||
import subprocess
|
||||
from scipy.constants import hbar, e as eV, pi, c
|
||||
|
||||
def make_action_sharedlist(opname, listname):
|
||||
class opAction(argparse.Action):
|
||||
def __call__(self, parser, args, values, option_string=None):
|
||||
if (not hasattr(args, listname)) or getattr(args, listname) is None:
|
||||
setattr(args, listname, list())
|
||||
getattr(args,listname).append((opname, values))
|
||||
return opAction
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
#TODO? použít type=argparse.FileType('r') ?
|
||||
parser.add_argument('--TMatrix', action='store', required=True, help='Path to TMatrix file')
|
||||
parser.add_argument('--griddir', action='store', required=True, help='Path to the directory with precalculated translation operators')
|
||||
#sizepar = parser.add_mutually_exclusive_group(required=True)
|
||||
parser.add_argument('--hexside', action='store', type=float, required=True, help='Lattice hexagon size length')
|
||||
parser.add_argument('--output', action='store', help='Path to output PDF')
|
||||
parser.add_argument('--store_SVD', action='store_true', help='If specified without --SVD_output, it will save the data in a file named as the PDF output, but with .npz extension instead')
|
||||
#parser.add_argument('--SVD_output', action='store', help='Path to output singular value decomposition result')
|
||||
parser.add_argument('--nSV', action='store', metavar='N', type=int, default=1, help='Store and draw N minimun singular values')
|
||||
parser.add_argument('--scp_to', action='store', metavar='N', type=str, help='SCP the output files to a given destination')
|
||||
parser.add_argument('--background_permittivity', action='store', type=float, default=1., help='Background medium relative permittivity (default 1)')
|
||||
parser.add_argument('--sparse', action='store', type=int, help='Skip frequencies for preview')
|
||||
parser.add_argument('--eVmax', action='store', type=float, help='Skip frequencies above this value')
|
||||
parser.add_argument('--eVmin', action='store', type=float, help='Skip frequencies below this value')
|
||||
parser.add_argument('--kdensity', action='store', type=int, default=66, help='Number of k-points per x-axis segment')
|
||||
parser.add_argument('--lMax', action='store', type=int, help='Override lMax from the TMatrix file')
|
||||
#TODO some more sophisticated x axis definitions
|
||||
parser.add_argument('--gaussian', action='store', type=float, metavar='σ', help='Use a gaussian envelope for weighting the interaction matrix contributions (depending on the distance), measured in unit cell lengths (?) FIxME).')
|
||||
popgrp=parser.add_argument_group(title='Operations')
|
||||
popgrp.add_argument('--tr', dest='ops', action=make_action_sharedlist('tr', 'ops'), default=list()) # the default value for dest can be set once
|
||||
popgrp.add_argument('--tr0', dest='ops', action=make_action_sharedlist('tr0', 'ops'))
|
||||
popgrp.add_argument('--tr1', dest='ops', action=make_action_sharedlist('tr1', 'ops'))
|
||||
popgrp.add_argument('--sym', dest='ops', action=make_action_sharedlist('sym', 'ops'))
|
||||
popgrp.add_argument('--sym0', dest='ops', action=make_action_sharedlist('sym0', 'ops'))
|
||||
popgrp.add_argument('--sym1', dest='ops', action=make_action_sharedlist('sym1', 'ops'))
|
||||
#popgrp.add_argument('--mult', dest='ops', nargs=3, metavar=('INCSPEC', 'SCATSPEC', 'MULTIPLIER'), action=make_action_sharedlist('mult', 'ops'))
|
||||
#popgrp.add_argument('--mult0', dest='ops', nargs=3, metavar=('INCSPEC', 'SCATSPEC', 'MULTIPLIER'), action=make_action_sharedlist('mult0', 'ops'))
|
||||
#popgrp.add_argument('--mult1', dest='ops', nargs=3, metavar=('INCSPEC', 'SCATSPEC', 'MULTIPLIER'), action=make_action_sharedlist('mult1', 'ops'))
|
||||
popgrp.add_argument('--multl', dest='ops', nargs=3, metavar=('INCL[,INCL,...]', 'SCATL[,SCATL,...]', 'MULTIPLIER'), action=make_action_sharedlist('multl', 'ops'))
|
||||
popgrp.add_argument('--multl0', dest='ops', nargs=3, metavar=('INCL[,INCL,...]', 'SCATL[,SCATL,...]', 'MULTIPLIER'), action=make_action_sharedlist('multl0', 'ops'))
|
||||
popgrp.add_argument('--multl1', dest='ops', nargs=3, metavar=('INCL[,INCL,...]', 'SCATL[,SCATL,...]', 'MULTIPLIER'), action=make_action_sharedlist('multl1', 'ops'))
|
||||
parser.add_argument('--frequency_multiplier', action='store', type=float, default=1., help='Multiplies the frequencies in the TMatrix file by a given factor.')
|
||||
# TODO enable more flexible per-sublattice specification
|
||||
pargs=parser.parse_args()
|
||||
print(pargs)
|
||||
|
||||
|
||||
translations_dir = pargs.griddir
|
||||
TMatrix_file = pargs.TMatrix
|
||||
pdfout = pargs.output if pargs.output else (''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10)) + '.pdf')
|
||||
print(pdfout)
|
||||
if(pargs.store_SVD):
|
||||
if re.search('.pdf$', pdfout):
|
||||
svdout = re.sub('.pdf$', r'.npz', pdfout)
|
||||
else:
|
||||
svdout = pdfout + '.npz'
|
||||
else:
|
||||
svdout = None
|
||||
|
||||
|
||||
hexside = pargs.hexside #375e-9
|
||||
epsilon_b = pargs.background_permittivity #2.3104
|
||||
gaussianSigma = pargs.gaussian if pargs.gaussian else None # hexside * 222 / 7
|
||||
interpfreqfactor = pargs.frequency_multiplier
|
||||
scp_dest = pargs.scp_to if pargs.scp_to else None
|
||||
kdensity = pargs.kdensity
|
||||
minfreq = pargs.eVmin*eV/hbar if pargs.eVmin else None
|
||||
maxfreq = pargs.eVmax*eV/hbar if pargs.eVmax else None
|
||||
skipfreq = pargs.sparse if pargs.sparse else None
|
||||
svn = pargs.nSV
|
||||
|
||||
# TODO multiplier operation definitions and parsing
|
||||
#factor13inc = 10
|
||||
#factor13scat=10
|
||||
|
||||
ops = list()
|
||||
opre = re.compile('(tr|sym|copy|multl|mult)(\d*)')
|
||||
for oparg in pargs.ops:
|
||||
opm = opre.match(oparg[0])
|
||||
if opm:
|
||||
ops.append(((opm.group(2),) if opm.group(2) else (0,1), opm.group(1), oparg[1]))
|
||||
else:
|
||||
raise # should not happen
|
||||
print(ops)
|
||||
|
||||
#ops = (
|
||||
# # co, typ operace (symetrizace / transformace / kopie), specifikace (operace nebo zdroj),
|
||||
# # co: 0, 1, (0,1), (0,), (1,), #NI: 'all'
|
||||
# # typ operace: sym, tr, copy
|
||||
# # specifikace:
|
||||
# # sym, tr: 'σ_z', 'σ_y', 'C2'; sym: 'C3',
|
||||
# # copy: 0, 1 (zdroj)
|
||||
# ((0,1), 'sym', 'σ_z'),
|
||||
# #((0,1), 'sym', 'σ_x'),
|
||||
# #((0,1), 'sym', 'σ_y'),
|
||||
# ((0,1), 'sym', 'C3'),
|
||||
# ((1), 'tr', 'C2'),
|
||||
#
|
||||
#)
|
||||
|
||||
# -----------------finished basic CLI parsing (except for op arguments) ------------------
|
||||
import time
|
||||
begtime=time.time()
|
||||
|
||||
from matplotlib.path import Path
|
||||
import matplotlib.patches as patches
|
||||
import matplotlib.pyplot as plt
|
||||
import qpms
|
||||
import numpy as np
|
||||
import os, sys, warnings, math
|
||||
from matplotlib import pyplot as plt
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
from scipy import interpolate
|
||||
nx = None
|
||||
s3 = math.sqrt(3)
|
||||
|
||||
|
||||
|
||||
pdf = PdfPages(pdfout)
|
||||
|
||||
# In[3]:
|
||||
|
||||
# specifikace T-matice zde
|
||||
cdn = c/ math.sqrt(epsilon_b)
|
||||
TMatrices_orig, freqs_orig, freqs_weirdunits_orig, lMaxTM = qpms.loadScuffTMatrices(TMatrix_file)
|
||||
if pargs.lMax:
|
||||
lMax = pargs.lMax if pargs.lMax else lMaxTM
|
||||
my, ny = qpms.get_mn_y(lMax)
|
||||
nelem = len(my)
|
||||
if pargs.lMax: #force commandline specified lMax
|
||||
TMatrices_orig = TMatrices_orig[...,0:nelem,:,0:nelem]
|
||||
|
||||
ž = np.arange(2*nelem)
|
||||
tž = ž // nelem
|
||||
mž = my[ž%nelem]
|
||||
nž = ny[ž%nelem]
|
||||
TEž = ž[(mž+nž+tž) % 2 == 0]
|
||||
TMž = ž[(mž+nž+tž) % 2 == 1]
|
||||
|
||||
č = np.arange(2*2*nelem)
|
||||
žč = č % (2* nelem)
|
||||
tč = tž[žč]
|
||||
mč = mž[žč]
|
||||
nč = nž[žč]
|
||||
TEč = č[(mč+nč+tč) % 2 == 0]
|
||||
TMč = č[(mč+nč+tč) % 2 == 1]
|
||||
|
||||
TMatrices = np.array(np.broadcast_to(TMatrices_orig[:,nx,:,:,:,:],(len(freqs_orig),2,2,nelem,2,nelem)) )
|
||||
|
||||
#TMatrices[:,:,:,:,:,ny==3] *= factor13inc
|
||||
#TMatrices[:,:,:,ny==3,:,:] *= factor13scat
|
||||
xfl = qpms.xflip_tyty(lMax)
|
||||
yfl = qpms.yflip_tyty(lMax)
|
||||
zfl = qpms.zflip_tyty(lMax)
|
||||
c2rot = qpms.apply_matrix_left(qpms.yflip_yy(3),qpms.xflip_yy(3),-1)
|
||||
|
||||
reCN = re.compile('(\d*)C(\d+)')
|
||||
#TODO C nekonečno
|
||||
|
||||
for op in ops:
|
||||
if op[0] == 'all':
|
||||
targets = (0,1)
|
||||
elif isinstance(op[0],int):
|
||||
targets = (op[0],)
|
||||
else:
|
||||
targets = op[0]
|
||||
|
||||
if op[1] == 'sym':
|
||||
mCN = reCN.match(op[2]) # Fuck van Rossum for not having assignments inside expressions
|
||||
if op[2] == 'σ_z':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(zfl,qpms.apply_ndmatrix_left(zfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'σ_y':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(yfl,qpms.apply_ndmatrix_left(yfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'σ_x':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(xfl,qpms.apply_ndmatrix_left(xfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'C2': # special case of the latter
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_matrix_left(c2rot,qpms.apply_matrix_left(c2rot, TMatrices[:,t], -3),-1))/2
|
||||
elif mCN:
|
||||
rotN = int(mCN.group(2))
|
||||
TMatrix_contribs = np.empty((rotN,TMatrices.shape[0],2,nelem,2,nelem), dtype=np.complex_)
|
||||
for t in targets:
|
||||
for i in range(rotN):
|
||||
rotangle = 2*np.pi*i / rotN
|
||||
rot = qpms.WignerD_yy_fromvector(lMax,np.array([0,0,rotangle]))
|
||||
rotinv = qpms.WignerD_yy_fromvector(lMax,np.array([0,0,-rotangle]))
|
||||
TMatrix_contribs[i] = qpms.apply_matrix_left(rot,qpms.apply_matrix_left(rotinv, TMatrices[:,t], -3),-1)
|
||||
TMatrices[:,t] = np.sum(TMatrix_contribs, axis=0) / rotN
|
||||
else:
|
||||
raise
|
||||
elif op[1] == 'tr':
|
||||
mCN = reCN.match(op[2]) # Fuck van Rossum for not having assignments inside expressions
|
||||
if op[2] == 'σ_z':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(zfl,qpms.apply_ndmatrix_left(zfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'σ_y':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(yfl,qpms.apply_ndmatrix_left(yfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'σ_x':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(xfl,qpms.apply_ndmatrix_left(xfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'C2':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_matrix_left(c2rot,qpms.apply_matrix_left(c2rot, TMatrices[:,t], -3),-1)
|
||||
elif mCN:
|
||||
rotN = int(mCN.group(2))
|
||||
power = int(mCN.group(1)) if mCN.group(1) else 1
|
||||
TMatrix_contribs = np.empty((rotN,TMatrices.shape[0],2,nelem,2,nelem), dtype=np.complex_)
|
||||
for t in targets:
|
||||
rotangle = 2*np.pi*power/rotN
|
||||
rot = qpms.WignerD_yy_fromvector(lMax, np.array([0,0,rotangle]))
|
||||
rotinv = qpms.WignerD_yy_fromvector(lMax, np.array([0,0,-rotangle]))
|
||||
TMatrices[:,t] = qpms.apply_matrix_left(rot, qpms.apply_matrix_left(rotinv, TMatrices[:,t], -3),-1)
|
||||
else:
|
||||
raise
|
||||
elif op[1] == 'copy':
|
||||
raise # not implemented
|
||||
elif op[1] == 'mult':
|
||||
raise # not implemented
|
||||
elif op[1] == 'multl':
|
||||
incy = np.full((nelem,), False, dtype=bool)
|
||||
for incl in op[2][0].split(','):
|
||||
l = int(incl)
|
||||
incy += (l == ny)
|
||||
scaty = np.full((nelem,), False, dtype=bool)
|
||||
for scatl in op[2][1].split(','):
|
||||
l = int(scatl)
|
||||
scaty += (l == ny)
|
||||
for t in targets:
|
||||
TMatrices[np.ix_(np.arange(TMatrices.shape[0]),np.array([t]),np.array([0,1]),scaty,np.array([0,1]),incy)] *= float(op[2][2])
|
||||
else:
|
||||
raise #unknown operation; should not happen
|
||||
|
||||
TMatrices_interp = interpolate.interp1d(freqs_orig*interpfreqfactor, TMatrices, axis=0, kind='linear',fill_value="extrapolate")
|
||||
|
||||
|
||||
|
||||
# In[4]:
|
||||
|
||||
om = np.linspace(np.min(freqs_orig), np.max(freqs_orig),100)
|
||||
TMatrix0ip = np.reshape(TMatrices_interp(om)[:,0], (len(om), 2*nelem*2*nelem))
|
||||
f, axa = plt.subplots(2, 2, figsize=(15,15))
|
||||
|
||||
#print(TMatrices.shape)
|
||||
#plt.plot(om, TMatrices[:,0,0,0,0].imag,'r',om, TMatrices[:,0,0,0,0].real,'r--',om, TMatrices[:,0,2,0,2].imag,'b',om, TMatrices[:,0,2,0,2].real,'b--'))
|
||||
|
||||
ax = axa[0,0]
|
||||
ax2 = ax.twiny()
|
||||
ax2.set_xlim([ax.get_xlim()[0]/eV*hbar,ax.get_xlim()[1]/eV*hbar])
|
||||
ax.plot(
|
||||
om, TMatrix0ip[:,:].imag,'-',om, TMatrix0ip[:,:].real,'--',
|
||||
)
|
||||
ax = axa[0,1]
|
||||
ax2 = ax.twiny()
|
||||
ax2.set_xlim([ax.get_xlim()[0]/eV*hbar,ax.get_xlim()[1]/eV*hbar])
|
||||
ax.plot(
|
||||
om, abs(TMatrix0ip[:,:]),'-'
|
||||
)
|
||||
ax.set_yscale('log')
|
||||
|
||||
ax = axa[1,1]
|
||||
ax2 = ax.twiny()
|
||||
ax2.set_xlim([ax.get_xlim()[0]/eV*hbar,ax.get_xlim()[1]/eV*hbar])
|
||||
ax.plot(
|
||||
om, np.unwrap(np.angle(TMatrix0ip[:,:]),axis=0),'-'
|
||||
)
|
||||
|
||||
ax = axa[1,0]
|
||||
ax.text(0.5,0.5,str(pargs).replace(',',',\n'),horizontalalignment='center',verticalalignment='center',transform=ax.transAxes)
|
||||
pdf.savefig(f)
|
||||
|
||||
|
||||
# In[ ]:
|
||||
|
||||
#kdensity = 66 #defined from cl arguments
|
||||
bz_0 = np.array((0,0,0.,))
|
||||
bz_K1 = np.array((1.,0,0))*4*np.pi/3/hexside/s3
|
||||
bz_K2 = np.array((1./2.,s3/2,0))*4*np.pi/3/hexside/s3
|
||||
bz_M = np.array((3./4, s3/4,0))*4*np.pi/3/hexside/s3
|
||||
k0Mlist = bz_0 + (bz_M-bz_0) * np.linspace(0,1,kdensity)[:,nx]
|
||||
kMK1list = bz_M + (bz_K1-bz_M) * np.linspace(0,1,kdensity)[:,nx]
|
||||
kK10list = bz_K1 + (bz_0-bz_K1) * np.linspace(0,1,kdensity)[:,nx]
|
||||
k0K2list = bz_0 + (bz_K2-bz_0) * np.linspace(0,1,kdensity)[:,nx]
|
||||
kK2Mlist = bz_K2 + (bz_M-bz_K2) * np.linspace(0,1,kdensity)[:,nx]
|
||||
B1 = 2* bz_K1 - bz_K2
|
||||
B2 = 2* bz_K2 - bz_K1
|
||||
klist = np.concatenate((k0Mlist,kMK1list,kK10list,k0K2list,kK2Mlist), axis=0)
|
||||
kxmaplist = np.concatenate((np.array([0]),np.cumsum(np.linalg.norm(np.diff(klist, axis=0), axis=-1))))
|
||||
|
||||
|
||||
# In[ ]:
|
||||
|
||||
n2id = np.identity(2*nelem)
|
||||
n2id.shape = (2,nelem,2,nelem)
|
||||
extlistlist = list()
|
||||
leftmatrixlistlist = list()
|
||||
minsvTElistlist=list()
|
||||
minsvTMlistlist=list()
|
||||
if svdout:
|
||||
svUfullTElistlist = list()
|
||||
svVfullTElistlist = list()
|
||||
svSfullTElistlist = list()
|
||||
svUfullTMlistlist = list()
|
||||
svVfullTMlistlist = list()
|
||||
svSfullTMlistlist = list()
|
||||
|
||||
nan = float('nan')
|
||||
omegalist = list()
|
||||
filecount = 0
|
||||
for trfile in os.scandir(translations_dir):
|
||||
filecount += 1
|
||||
if (skipfreq and filecount % skipfreq):
|
||||
continue
|
||||
try:
|
||||
npz = np.load(trfile.path, mmap_mode='r')
|
||||
k_0 = npz['precalc_params'][()]['k_hexside'] / hexside
|
||||
omega = k_0 * c / math.sqrt(epsilon_b)
|
||||
if((minfreq and omega < minfreq) or (maxfreq and omega > maxfreq)):
|
||||
continue
|
||||
except:
|
||||
print ("Unexpected error, trying to continue with another file:", sys.exc_info()[0])
|
||||
continue
|
||||
try:
|
||||
tdic = qpms.hexlattice_precalc_AB_loadunwrap(trfile.path, return_points=True)
|
||||
except:
|
||||
print ("Unexpected error, trying to continue with another file:", sys.exc_info()[0])
|
||||
continue
|
||||
k_0 = tdic['k_hexside'] / hexside
|
||||
omega = k_0 * c / math.sqrt(epsilon_b)
|
||||
omegalist.append(omega)
|
||||
print(filecount, omega/eV*hbar)
|
||||
sys.stdout.flush()
|
||||
a_self = tdic['a_self'][:,:nelem,:nelem]
|
||||
b_self = tdic['b_self'][:,:nelem,:nelem]
|
||||
a_u2d = tdic['a_u2d'][:,:nelem,:nelem]
|
||||
b_u2d = tdic['b_u2d'][:,:nelem,:nelem]
|
||||
a_d2u = tdic['a_d2u'][:,:nelem,:nelem]
|
||||
b_d2u = tdic['b_d2u'][:,:nelem,:nelem]
|
||||
unitcell_translations = tdic['self_tr']*hexside*s3
|
||||
u2d_translations = tdic['u2d_tr']*hexside*s3
|
||||
d2u_translations = tdic['d2u_tr']*hexside*s3
|
||||
if gaussianSigma:
|
||||
unitcell_envelope = np.exp(-np.sum(tdic['self_tr']**2,axis=-1)/(2*gaussianSigma**2))
|
||||
u2d_envelope = np.exp(-np.sum(tdic['u2d_tr']**2,axis=-1)/(2*gaussianSigma**2))
|
||||
d2u_envelope = np.exp(-np.sum(tdic['d2u_tr']**2,axis=-1)/(2*gaussianSigma**2))
|
||||
|
||||
|
||||
TMatrices_om = TMatrices_interp(omega)
|
||||
if svdout:
|
||||
svUfullTElist = np.full((klist.shape[0], 2*nelem, 2*nelem), np.nan, dtype=complex)
|
||||
svVfullTElist = np.full((klist.shape[0], 2*nelem, 2*nelem), np.nan, dtype=complex)
|
||||
svSfullTElist = np.full((klist.shape[0], 2*nelem), np.nan, dtype=complex)
|
||||
svUfullTMlist = np.full((klist.shape[0], 2*nelem, 2*nelem), np.nan, dtype=complex)
|
||||
svVfullTMlist = np.full((klist.shape[0], 2*nelem, 2*nelem), np.nan, dtype=complex)
|
||||
svSfullTMlist = np.full((klist.shape[0], 2*nelem), np.nan, dtype=complex)
|
||||
|
||||
|
||||
minsvTElist = np.full((klist.shape[0], svn),np.nan)
|
||||
minsvTMlist = np.full((klist.shape[0], svn),np.nan)
|
||||
leftmatrixlist = np.full((klist.shape[0],2,2,nelem,2,2,nelem),np.nan,dtype=complex)
|
||||
isNaNlist = np.zeros((klist.shape[0]), dtype=bool)
|
||||
|
||||
# sem nějaká rozumná smyčka
|
||||
for ki in range(klist.shape[0]):
|
||||
k = klist[ki]
|
||||
if (k_0*k_0 - k[0]*k[0] - k[1]*k[1] < 0):
|
||||
isNaNlist[ki] = True
|
||||
continue
|
||||
|
||||
phases_self = np.exp(1j*np.tensordot(k,unitcell_translations,axes=(0,-1)))
|
||||
phases_u2d = np.exp(1j*np.tensordot(k,u2d_translations,axes=(0,-1)))
|
||||
phases_d2u = np.exp(1j*np.tensordot(k,d2u_translations,axes=(0,-1)))
|
||||
if gaussianSigma:
|
||||
phases_self *= unitcell_envelope
|
||||
phases_u2d *= u2d_envelope
|
||||
phases_d2u *= d2u_envelope
|
||||
leftmatrix = np.zeros((2,2,nelem, 2,2,nelem), dtype=complex)
|
||||
|
||||
leftmatrix[0,0,:,0,0,:] = np.tensordot(a_self,phases_self, axes=(0,-1)) # u2u, E2E
|
||||
leftmatrix[1,0,:,1,0,:] = leftmatrix[0,0,:,0,0,:] # d2d, E2E
|
||||
leftmatrix[0,1,:,0,1,:] = leftmatrix[0,0,:,0,0,:] # u2u, M2M
|
||||
leftmatrix[1,1,:,1,1,:] = leftmatrix[0,0,:,0,0,:] # d2d, M2M
|
||||
leftmatrix[0,0,:,0,1,:] = np.tensordot(b_self,phases_self, axes=(0,-1)) # u2u, M2E
|
||||
leftmatrix[0,1,:,0,0,:] = leftmatrix[0,0,:,0,1,:] # u2u, E2M
|
||||
leftmatrix[1,1,:,1,0,:] = leftmatrix[0,0,:,0,1,:] # d2d, E2M
|
||||
leftmatrix[1,0,:,1,1,:] = leftmatrix[0,0,:,0,1,:] # d2d, M2E
|
||||
leftmatrix[0,0,:,1,0,:] = np.tensordot(a_d2u, phases_d2u,axes=(0,-1)) #d2u,E2E
|
||||
leftmatrix[0,1,:,1,1,:] = leftmatrix[0,0,:,1,0,:] #d2u, M2M
|
||||
leftmatrix[1,0,:,0,0,:] = np.tensordot(a_u2d, phases_u2d,axes=(0,-1)) #u2d,E2E
|
||||
leftmatrix[1,1,:,0,1,:] = leftmatrix[1,0,:,0,0,:] #u2d, M2M
|
||||
leftmatrix[0,0,:,1,1,:] = np.tensordot(b_d2u, phases_d2u,axes=(0,-1)) #d2u,M2E
|
||||
leftmatrix[0,1,:,1,0,:] = leftmatrix[0,0,:,1,1,:] #d2u, E2M
|
||||
leftmatrix[1,0,:,0,1,:] = np.tensordot(b_u2d, phases_u2d,axes=(0,-1)) #u2d,M2E
|
||||
leftmatrix[1,1,:,0,0,:] = leftmatrix[1,0,:,0,1,:] #u2d, E2M
|
||||
#leftmatrix is now the translation matrix T
|
||||
for j in range(2):
|
||||
leftmatrix[j] = -np.tensordot(TMatrices_om[j], leftmatrix[j], axes=([-2,-1],[0,1]))
|
||||
# at this point, jth row of leftmatrix is that of -MT
|
||||
leftmatrix[j,:,:,j,:,:] += n2id
|
||||
#now we are done, 1-MT
|
||||
|
||||
leftmatrixlist[ki] = leftmatrix
|
||||
|
||||
|
||||
nnlist = np.logical_not(isNaNlist)
|
||||
leftmatrixlist_s = np.reshape(leftmatrixlist,(klist.shape[0], 2*2*nelem,2*2*nelem))[nnlist]
|
||||
leftmatrixlist_TE = leftmatrixlist_s[np.ix_(np.arange(leftmatrixlist_s.shape[0]),TEč,TEč)]
|
||||
leftmatrixlist_TM = leftmatrixlist_s[np.ix_(np.arange(leftmatrixlist_s.shape[0]),TMč,TMč)]
|
||||
#svarr = np.linalg.svd(leftmatrixlist_TE, compute_uv=False)
|
||||
#argsortlist = np.argsort(svarr, axis=-1)[...,:svn]
|
||||
#minsvTElist[nnlist] = svarr[...,argsortlist]
|
||||
#minsvTElist[nnlist] = np.amin(np.linalg.svd(leftmatrixlist_TE, compute_uv=False), axis=-1)
|
||||
if svdout:
|
||||
svUfullTElist[nnlist], svSfullTElist[nnlist], svVfullTElist[nnlist] = np.linalg.svd(leftmatrixlist_TE, compute_uv=True)
|
||||
svUfullTMlist[nnlist], svSfullTMlist[nnlist], svVfullTMlist[nnlist] = np.linalg.svd(leftmatrixlist_TM, compute_uv=True)
|
||||
svUfullTElistlist.append(svUfullTElist)
|
||||
svVfullTElistlist.append(svVfullTElist)
|
||||
svSfullTElistlist.append(svSfullTElist)
|
||||
svUfullTMlistlist.append(svUfullTMlist)
|
||||
svVfullTMlistlist.append(svVfullTMlist)
|
||||
svSfullTMlistlist.append(svSfullTMlist)
|
||||
minsvTElist[nnlist] = np.linalg.svd(leftmatrixlist_TE, compute_uv=False)[...,-svn:]
|
||||
#svarr = np.linalg.svd(leftmatrixlist_TM, compute_uv=False)
|
||||
#argsortlist = np.argsort(svarr, axis=-1)[...,:svn]
|
||||
#minsvTMlist[nnlist] = svarr[...,argsortlist]
|
||||
#minsvTMlist[nnlist] = np.amin(np.linalg.svd(leftmatrixlist_TM, compute_uv=False), axis=-1)
|
||||
minsvTMlist[nnlist] = np.linalg.svd(leftmatrixlist_TM, compute_uv=False)[...,-svn:]
|
||||
minsvTMlistlist.append(minsvTMlist)
|
||||
minsvTElistlist.append(minsvTElist)
|
||||
|
||||
minsvTElistarr = np.array(minsvTElistlist)
|
||||
minsvTMlistarr = np.array(minsvTMlistlist)
|
||||
del minsvTElistlist, minsvTMlistlist
|
||||
if svdout:
|
||||
svUfullTElistarr = np.array(svUfullTElistlist)
|
||||
svVfullTElistarr = np.array(svVfullTElistlist)
|
||||
svSfullTElistarr = np.array(svSfullTElistlist)
|
||||
del svUfullTElistlist, svVfullTElistlist, svSfullTElistlist
|
||||
svUfullTMlistarr = np.array(svUfullTMlistlist)
|
||||
svVfullTMlistarr = np.array(svVfullTMlistlist)
|
||||
svSfullTMlistarr = np.array(svSfullTMlistlist)
|
||||
del svUfullTMlistlist, svVfullTMlistlist, svSfullTMlistlist
|
||||
omegalist = np.array(omegalist)
|
||||
# order to make the scatter plots "nice"
|
||||
omegaorder = np.argsort(omegalist)
|
||||
omegalist = omegalist[omegaorder]
|
||||
minsvTElistarr = minsvTElistarr[omegaorder]
|
||||
minsvTMlistarr = minsvTMlistarr[omegaorder]
|
||||
if svdout:
|
||||
svUfullTElistarr = svUfullTElistarr[omegaorder]
|
||||
svVfullTElistarr = svVfullTElistarr[omegaorder]
|
||||
svSfullTElistarr = svSfullTElistarr[omegaorder]
|
||||
svUfullTMlistarr = svUfullTMlistarr[omegaorder]
|
||||
svVfullTMlistarr = svVfullTMlistarr[omegaorder]
|
||||
svSfullTMlistarr = svSfullTMlistarr[omegaorder]
|
||||
np.savez(svdout, omega = omegalist, klist = klist, bzpoints = np.array([bz_0, bz_K1, bz_K2, bz_M, B1, B2]),
|
||||
uTE = svUfullTElistarr,
|
||||
vTE = svVfullTElistarr,
|
||||
sTE = svSfullTElistarr,
|
||||
uTM = svUfullTMlistarr,
|
||||
vTM = svVfullTMlistarr,
|
||||
sTM = svSfullTMlistarr,
|
||||
)
|
||||
|
||||
|
||||
omlist = np.broadcast_to(omegalist[:,nx], minsvTElistarr[...,0].shape)
|
||||
kxmlarr = np.broadcast_to(kxmaplist[nx,:], minsvTElistarr[...,0].shape)
|
||||
klist = np.concatenate((k0Mlist,kMK1list,kK10list,k0K2list,kK2Mlist), axis=0)
|
||||
|
||||
|
||||
# In[ ]:
|
||||
for minN in reversed(range(svn)):
|
||||
f, ax = plt.subplots(1, figsize=(20,15))
|
||||
sc = ax.scatter(kxmlarr, omlist/eV*hbar, c = np.sqrt(minsvTMlistarr[...,minN]), s =40, lw=0)
|
||||
ax.plot(kxmaplist, np.linalg.norm(klist,axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist+B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist+B2, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-B2, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist+B2-B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-B2+B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-B2-B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist+B2+B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-2*B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-2*B2, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-2*B2-B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-2*B1-B2, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-2*B1-2*B2, axis=-1)*cdn/eV*hbar, '-',
|
||||
# kxmaplist, np.linalg.norm(klist+2*B2-B1, axis=-1)*cdn, '-',
|
||||
# kxmaplist, np.linalg.norm(klist+2*B1-B2, axis=-1)*cdn, '-',
|
||||
)
|
||||
ax.set_xlim([np.min(kxmlarr),np.max(kxmlarr)])
|
||||
#ax.set_ylim([2.15,2.30])
|
||||
ax.set_ylim([np.min(omlist/eV*hbar),np.max(omlist/eV*hbar)])
|
||||
ax.set_xticks([0, kxmaplist[len(k0Mlist)-1], kxmaplist[len(k0Mlist)+len(kMK1list)-1], kxmaplist[len(k0Mlist)+len(kMK1list)+len(kK10list)-1], kxmaplist[len(k0Mlist)+len(kMK1list)+len(kK10list)+len(k0K2list)-1], kxmaplist[len(k0Mlist)+len(kMK1list)+len(kK10list)+len(k0K2list)+len(kK2Mlist)-1]])
|
||||
ax.set_xticklabels(['Γ', 'M', 'K', 'Γ', 'K\'','M'])
|
||||
f.colorbar(sc)
|
||||
|
||||
pdf.savefig(f)
|
||||
|
||||
|
||||
# In[ ]:
|
||||
|
||||
f, ax = plt.subplots(1, figsize=(20,15))
|
||||
sc = ax.scatter(kxmlarr, omlist/eV*hbar, c = np.sqrt(minsvTElistarr[...,minN]), s =40, lw=0)
|
||||
ax.plot(kxmaplist, np.linalg.norm(klist,axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist+B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist+B2, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-B2, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist+B2-B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-B2+B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-B2-B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist+B2+B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-2*B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-2*B2, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-2*B2-B1, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-2*B1-B2, axis=-1)*cdn/eV*hbar, '-',
|
||||
kxmaplist, np.linalg.norm(klist-2*B1-2*B2, axis=-1)*cdn/eV*hbar, '-',
|
||||
# kxmaplist, np.linalg.norm(klist+2*B2-B1, axis=-1)*cdn, '-',
|
||||
# kxmaplist, np.linalg.norm(klist+2*B1-B2, axis=-1)*cdn, '-',
|
||||
)
|
||||
ax.set_xlim([np.min(kxmlarr),np.max(kxmlarr)])
|
||||
#ax.set_ylim([2.15,2.30])
|
||||
ax.set_ylim([np.min(omlist/eV*hbar),np.max(omlist/eV*hbar)])
|
||||
ax.set_xticks([0, kxmaplist[len(k0Mlist)-1], kxmaplist[len(k0Mlist)+len(kMK1list)-1], kxmaplist[len(k0Mlist)+len(kMK1list)+len(kK10list)-1], kxmaplist[len(k0Mlist)+len(kMK1list)+len(kK10list)+len(k0K2list)-1], kxmaplist[len(k0Mlist)+len(kMK1list)+len(kK10list)+len(k0K2list)+len(kK2Mlist)-1]])
|
||||
ax.set_xticklabels(['Γ', 'M', 'K', 'Γ', 'K\'','M'])
|
||||
f.colorbar(sc)
|
||||
|
||||
pdf.savefig(f)
|
||||
pdf.close()
|
||||
|
||||
if scp_dest:
|
||||
subprocess.run(['scp', pdfout, scp_dest])
|
||||
if svdout:
|
||||
subprocess.run(['scp', svdout, scp_dest])
|
||||
|
||||
print(time.strftime("%H.%M:%S",time.gmtime(time.time()-begtime)))
|
|
@ -1,403 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
|
||||
import argparse, re, random, string
|
||||
import subprocess
|
||||
from scipy.constants import hbar, e as eV, pi, c
|
||||
|
||||
def make_action_sharedlist(opname, listname):
|
||||
class opAction(argparse.Action):
|
||||
def __call__(self, parser, args, values, option_string=None):
|
||||
if (not hasattr(args, listname)) or getattr(args, listname) is None:
|
||||
setattr(args, listname, list())
|
||||
getattr(args,listname).append((opname, values))
|
||||
return opAction
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
#TODO? použít type=argparse.FileType('r') ?
|
||||
parser.add_argument('--TMatrix', action='store', required=True, help='Path to TMatrix file')
|
||||
#parser.add_argument('--griddir', action='store', required=True, help='Path to the directory with precalculated translation operators')
|
||||
parser.add_argument('--output_prefix', action='store', required=True, help='Prefix to the pdf and/or npz output (will be appended frequency and hexside)')
|
||||
#sizepar = parser.add_mutually_exclusive_group(required=True)
|
||||
parser.add_argument('--hexside', action='store', type=float, required=True, help='Lattice hexagon size length')
|
||||
parser.add_argument('--output', action='store', help='Path to output PDF')
|
||||
parser.add_argument('--store_SVD', action='store_false', help='If specified without --SVD_output, it will save the data in a file named as the PDF output, but with .npz extension instead')
|
||||
parser.add_argument('--plot_TMatrix', action='store_true', help='Visualise TMatrix on the first page of the output')
|
||||
#parser.add_argument('--SVD_output', action='store', help='Path to output singular value decomposition result')
|
||||
parser.add_argument('--nSV', action='store', metavar='N', type=int, default=1, help='Store and draw N minimun singular values')
|
||||
parser.add_argument('--maxlayer', action='store', type=int, default=100, help='How far to sum the lattice points to obtain the dispersion')
|
||||
parser.add_argument('--scp_to', action='store', metavar='N', type=str, help='SCP the output files to a given destination')
|
||||
parser.add_argument('--background_permittivity', action='store', type=float, default=1., help='Background medium relative permittivity (default 1)')
|
||||
parser.add_argument('--eVfreq', action='store', required=True, type=float, help='Frequency in eV')
|
||||
parser.add_argument('--kdensity', action='store', type=int, default=33, help='Number of k-points per x-axis segment')
|
||||
parser.add_argument('--lMax', action='store', type=int, help='Override lMax from the TMatrix file')
|
||||
#TODO some more sophisticated x axis definitions
|
||||
parser.add_argument('--gaussian', action='store', type=float, metavar='σ', help='Use a gaussian envelope for weighting the interaction matrix contributions (depending on the distance), measured in unit cell lengths (?) FIxME).')
|
||||
popgrp=parser.add_argument_group(title='Operations')
|
||||
popgrp.add_argument('--tr', dest='ops', action=make_action_sharedlist('tr', 'ops'), default=list()) # the default value for dest can be set once
|
||||
popgrp.add_argument('--tr0', dest='ops', action=make_action_sharedlist('tr0', 'ops'))
|
||||
popgrp.add_argument('--tr1', dest='ops', action=make_action_sharedlist('tr1', 'ops'))
|
||||
popgrp.add_argument('--sym', dest='ops', action=make_action_sharedlist('sym', 'ops'))
|
||||
popgrp.add_argument('--sym0', dest='ops', action=make_action_sharedlist('sym0', 'ops'))
|
||||
popgrp.add_argument('--sym1', dest='ops', action=make_action_sharedlist('sym1', 'ops'))
|
||||
#popgrp.add_argument('--mult', dest='ops', nargs=3, metavar=('INCSPEC', 'SCATSPEC', 'MULTIPLIER'), action=make_action_sharedlist('mult', 'ops'))
|
||||
#popgrp.add_argument('--mult0', dest='ops', nargs=3, metavar=('INCSPEC', 'SCATSPEC', 'MULTIPLIER'), action=make_action_sharedlist('mult0', 'ops'))
|
||||
#popgrp.add_argument('--mult1', dest='ops', nargs=3, metavar=('INCSPEC', 'SCATSPEC', 'MULTIPLIER'), action=make_action_sharedlist('mult1', 'ops'))
|
||||
popgrp.add_argument('--multl', dest='ops', nargs=3, metavar=('INCL[,INCL,...]', 'SCATL[,SCATL,...]', 'MULTIPLIER'), action=make_action_sharedlist('multl', 'ops'))
|
||||
popgrp.add_argument('--multl0', dest='ops', nargs=3, metavar=('INCL[,INCL,...]', 'SCATL[,SCATL,...]', 'MULTIPLIER'), action=make_action_sharedlist('multl0', 'ops'))
|
||||
popgrp.add_argument('--multl1', dest='ops', nargs=3, metavar=('INCL[,INCL,...]', 'SCATL[,SCATL,...]', 'MULTIPLIER'), action=make_action_sharedlist('multl1', 'ops'))
|
||||
parser.add_argument('--frequency_multiplier', action='store', type=float, default=1., help='Multiplies the frequencies in the TMatrix file by a given factor.')
|
||||
# TODO enable more flexible per-sublattice specification
|
||||
pargs=parser.parse_args()
|
||||
print(pargs)
|
||||
|
||||
maxlayer=pargs.maxlayer
|
||||
hexside=pargs.hexside
|
||||
eVfreq = pargs.eVfreq
|
||||
freq = eVfreq*eV/hbar
|
||||
|
||||
TMatrix_file = pargs.TMatrix
|
||||
pdfout = pargs.output if pargs.output else (
|
||||
'%s_%dnm_%.4f.pdf' % (pargs.output_prefix,hexside/1e-9,eVfreq) if pargs.output_prefix else
|
||||
(''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10)) + '.pdf'))
|
||||
print(pdfout)
|
||||
if(pargs.store_SVD):
|
||||
if re.search('.pdf$', pdfout):
|
||||
svdout = re.sub('.pdf$', r'.npz', pdfout)
|
||||
else:
|
||||
svdout = pdfout + '.npz'
|
||||
else:
|
||||
svdout = None
|
||||
|
||||
|
||||
epsilon_b = pargs.background_permittivity #2.3104
|
||||
gaussianSigma = pargs.gaussian if pargs.gaussian else None # hexside * 222 / 7
|
||||
interpfreqfactor = pargs.frequency_multiplier
|
||||
scp_dest = pargs.scp_to if pargs.scp_to else None
|
||||
kdensity = pargs.kdensity
|
||||
svn = pargs.nSV
|
||||
|
||||
# TODO multiplier operation definitions and parsing
|
||||
#factor13inc = 10
|
||||
#factor13scat=10
|
||||
|
||||
ops = list()
|
||||
opre = re.compile('(tr|sym|copy|multl|mult)(\d*)')
|
||||
for oparg in pargs.ops:
|
||||
opm = opre.match(oparg[0])
|
||||
if opm:
|
||||
ops.append(((opm.group(2),) if opm.group(2) else (0,1), opm.group(1), oparg[1]))
|
||||
else:
|
||||
raise # should not happen
|
||||
print(ops)
|
||||
|
||||
#ops = (
|
||||
# # co, typ operace (symetrizace / transformace / kopie), specifikace (operace nebo zdroj),
|
||||
# # co: 0, 1, (0,1), (0,), (1,), #NI: 'all'
|
||||
# # typ operace: sym, tr, copy
|
||||
# # specifikace:
|
||||
# # sym, tr: 'σ_z', 'σ_y', 'C2'; sym: 'C3',
|
||||
# # copy: 0, 1 (zdroj)
|
||||
# ((0,1), 'sym', 'σ_z'),
|
||||
# #((0,1), 'sym', 'σ_x'),
|
||||
# #((0,1), 'sym', 'σ_y'),
|
||||
# ((0,1), 'sym', 'C3'),
|
||||
# ((1), 'tr', 'C2'),
|
||||
#
|
||||
#)
|
||||
|
||||
# -----------------finished basic CLI parsing (except for op arguments) ------------------
|
||||
import time
|
||||
begtime=time.time()
|
||||
|
||||
from matplotlib.path import Path
|
||||
import matplotlib.patches as patches
|
||||
import matplotlib.pyplot as plt
|
||||
import qpms
|
||||
import numpy as np
|
||||
import os, sys, warnings, math
|
||||
from matplotlib import pyplot as plt
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
from scipy import interpolate
|
||||
nx = None
|
||||
s3 = math.sqrt(3)
|
||||
|
||||
|
||||
|
||||
pdf = PdfPages(pdfout)
|
||||
|
||||
# In[3]:
|
||||
|
||||
# specifikace T-matice zde
|
||||
cdn = c/ math.sqrt(epsilon_b)
|
||||
TMatrices_orig, freqs_orig, freqs_weirdunits_orig, lMaxTM = qpms.loadScuffTMatrices(TMatrix_file)
|
||||
lMax = lMaxTM
|
||||
if pargs.lMax:
|
||||
lMax = pargs.lMax if pargs.lMax else lMaxTM
|
||||
my, ny = qpms.get_mn_y(lMax)
|
||||
nelem = len(my)
|
||||
if pargs.lMax: #force commandline specified lMax
|
||||
TMatrices_orig = TMatrices_orig[...,0:nelem,:,0:nelem]
|
||||
|
||||
TMatrices = np.array(np.broadcast_to(TMatrices_orig[:,nx,:,:,:,:],(len(freqs_orig),2,2,nelem,2,nelem)) )
|
||||
|
||||
#TMatrices[:,:,:,:,:,ny==3] *= factor13inc
|
||||
#TMatrices[:,:,:,ny==3,:,:] *= factor13scat
|
||||
xfl = qpms.xflip_tyty(lMax)
|
||||
yfl = qpms.yflip_tyty(lMax)
|
||||
zfl = qpms.zflip_tyty(lMax)
|
||||
c2rot = qpms.apply_matrix_left(qpms.yflip_yy(3),qpms.xflip_yy(3),-1)
|
||||
|
||||
reCN = re.compile('(\d*)C(\d+)')
|
||||
#TODO C nekonečno
|
||||
|
||||
for op in ops:
|
||||
if op[0] == 'all':
|
||||
targets = (0,1)
|
||||
elif isinstance(op[0],int):
|
||||
targets = (op[0],)
|
||||
else:
|
||||
targets = op[0]
|
||||
|
||||
if op[1] == 'sym':
|
||||
mCN = reCN.match(op[2]) # Fuck van Rossum for not having assignments inside expressions
|
||||
if op[2] == 'σ_z':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(zfl,qpms.apply_ndmatrix_left(zfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'σ_y':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(yfl,qpms.apply_ndmatrix_left(yfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'σ_x':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(xfl,qpms.apply_ndmatrix_left(xfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'C2': # special case of the latter
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_matrix_left(c2rot,qpms.apply_matrix_left(c2rot, TMatrices[:,t], -3),-1))/2
|
||||
elif mCN:
|
||||
rotN = int(mCN.group(2))
|
||||
TMatrix_contribs = np.empty((rotN,TMatrices.shape[0],2,nelem,2,nelem), dtype=np.complex_)
|
||||
for t in targets:
|
||||
for i in range(rotN):
|
||||
rotangle = 2*np.pi*i / rotN
|
||||
rot = qpms.WignerD_yy_fromvector(lMax,np.array([0,0,rotangle]))
|
||||
rotinv = qpms.WignerD_yy_fromvector(lMax,np.array([0,0,-rotangle]))
|
||||
TMatrix_contribs[i] = qpms.apply_matrix_left(rot,qpms.apply_matrix_left(rotinv, TMatrices[:,t], -3),-1)
|
||||
TMatrices[:,t] = np.sum(TMatrix_contribs, axis=0) / rotN
|
||||
else:
|
||||
raise
|
||||
elif op[1] == 'tr':
|
||||
mCN = reCN.match(op[2]) # Fuck van Rossum for not having assignments inside expressions
|
||||
if op[2] == 'σ_z':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(zfl,qpms.apply_ndmatrix_left(zfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'σ_y':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(yfl,qpms.apply_ndmatrix_left(yfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'σ_x':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(xfl,qpms.apply_ndmatrix_left(xfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'C2':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_matrix_left(c2rot,qpms.apply_matrix_left(c2rot, TMatrices[:,t], -3),-1)
|
||||
elif mCN:
|
||||
rotN = int(mCN.group(2))
|
||||
power = int(mCN.group(1)) if mCN.group(1) else 1
|
||||
TMatrix_contribs = np.empty((rotN,TMatrices.shape[0],2,nelem,2,nelem), dtype=np.complex_)
|
||||
for t in targets:
|
||||
rotangle = 2*np.pi*power/rotN
|
||||
rot = qpms.WignerD_yy_fromvector(lMax, np.array([0,0,rotangle]))
|
||||
rotinv = qpms.WignerD_yy_fromvector(lMax, np.array([0,0,-rotangle]))
|
||||
TMatrices[:,t] = qpms.apply_matrix_left(rot, qpms.apply_matrix_left(rotinv, TMatrices[:,t], -3),-1)
|
||||
else:
|
||||
raise
|
||||
elif op[1] == 'copy':
|
||||
raise # not implemented
|
||||
elif op[1] == 'mult':
|
||||
raise # not implemented
|
||||
elif op[1] == 'multl':
|
||||
incy = np.full((nelem,), False, dtype=bool)
|
||||
for incl in op[2][0].split(','):
|
||||
l = int(incl)
|
||||
incy += (l == ny)
|
||||
scaty = np.full((nelem,), False, dtype=bool)
|
||||
for scatl in op[2][1].split(','):
|
||||
l = int(scatl)
|
||||
scaty += (l == ny)
|
||||
for t in targets:
|
||||
TMatrices[np.ix_(np.arange(TMatrices.shape[0]),np.array([t]),np.array([0,1]),scaty,np.array([0,1]),incy)] *= float(op[2][2])
|
||||
else:
|
||||
raise #unknown operation; should not happen
|
||||
|
||||
TMatrices_interp = interpolate.interp1d(freqs_orig*interpfreqfactor, TMatrices, axis=0, kind='linear',fill_value="extrapolate")
|
||||
|
||||
|
||||
|
||||
# In[4]:
|
||||
if(pargs.plot_TMatrix):
|
||||
om = np.linspace(np.min(freqs_orig), np.max(freqs_orig),100)
|
||||
TMatrix0ip = np.reshape(TMatrices_interp(om)[:,0], (len(om), 2*nelem*2*nelem))
|
||||
f, axa = plt.subplots(2, 2, figsize=(15,15))
|
||||
|
||||
#print(TMatrices.shape)
|
||||
#plt.plot(om, TMatrices[:,0,0,0,0].imag,'r',om, TMatrices[:,0,0,0,0].real,'r--',om, TMatrices[:,0,2,0,2].imag,'b',om, TMatrices[:,0,2,0,2].real,'b--'))
|
||||
|
||||
ax = axa[0,0]
|
||||
ax2 = ax.twiny()
|
||||
ax2.set_xlim([ax.get_xlim()[0]/eV*hbar,ax.get_xlim()[1]/eV*hbar])
|
||||
ax.plot(
|
||||
om, TMatrix0ip[:,:].imag,'-',om, TMatrix0ip[:,:].real,'--',
|
||||
)
|
||||
ax = axa[0,1]
|
||||
ax2 = ax.twiny()
|
||||
ax2.set_xlim([ax.get_xlim()[0]/eV*hbar,ax.get_xlim()[1]/eV*hbar])
|
||||
ax.plot(
|
||||
om, abs(TMatrix0ip[:,:]),'-'
|
||||
)
|
||||
ax.set_yscale('log')
|
||||
|
||||
ax = axa[1,1]
|
||||
ax2 = ax.twiny()
|
||||
ax2.set_xlim([ax.get_xlim()[0]/eV*hbar,ax.get_xlim()[1]/eV*hbar])
|
||||
ax.plot(
|
||||
om, np.unwrap(np.angle(TMatrix0ip[:,:]),axis=0),'-'
|
||||
)
|
||||
|
||||
ax = axa[1,0]
|
||||
ax.text(0.5,0.5,str(pargs).replace(',',',\n'),horizontalalignment='center',verticalalignment='center',transform=ax.transAxes)
|
||||
pdf.savefig(f)
|
||||
|
||||
|
||||
# In[ ]:
|
||||
|
||||
'''
|
||||
#kdensity = 66 #defined from cl arguments
|
||||
bz_0 = np.array((0,0,0.,))
|
||||
bz_K1 = np.array((1.,0,0))*4*np.pi/3/hexside/s3
|
||||
bz_K2 = np.array((1./2.,s3/2,0))*4*np.pi/3/hexside/s3
|
||||
bz_M = np.array((3./4, s3/4,0))*4*np.pi/3/hexside/s3
|
||||
k0Mlist = bz_0 + (bz_M-bz_0) * np.linspace(0,1,kdensity)[:,nx]
|
||||
kMK1list = bz_M + (bz_K1-bz_M) * np.linspace(0,1,kdensity)[:,nx]
|
||||
kK10list = bz_K1 + (bz_0-bz_K1) * np.linspace(0,1,kdensity)[:,nx]
|
||||
k0K2list = bz_0 + (bz_K2-bz_0) * np.linspace(0,1,kdensity)[:,nx]
|
||||
kK2Mlist = bz_K2 + (bz_M-bz_K2) * np.linspace(0,1,kdensity)[:,nx]
|
||||
B1 = 2* bz_K1 - bz_K2
|
||||
B2 = 2* bz_K2 - bz_K1
|
||||
klist = np.concatenate((k0Mlist,kMK1list,kK10list,k0K2list,kK2Mlist), axis=0)
|
||||
kxmaplist = np.concatenate((np.array([0]),np.cumsum(np.linalg.norm(np.diff(klist, axis=0), axis=-1))))
|
||||
'''
|
||||
klist = qpms.generate_trianglepoints(kdensity, v3d=True, include_origin=True)*3*math.pi/(3*kdensity*hexside)
|
||||
TMatrices_om = TMatrices_interp(freq)
|
||||
|
||||
svdres = qpms.hexlattice_zsym_getSVD(lMax=lMax, TMatrices_om=TMatrices_om, epsilon_b=epsilon_b, hexside=hexside, maxlayer=maxlayer,
|
||||
omega=freq, klist=klist, gaussianSigma=gaussianSigma, onlyNmin=(0 if svdout else svn))
|
||||
if svdout:
|
||||
((svUfullTElist, svSfullTElist, svVfullTElist), (svUfullTMlist, svSfullTMlist, svVfullTMlist)) = svdres
|
||||
(minsvElist, minsvTMlist) = (svSfullTElist[...,-svn:], svSfullTMlist[...,-svn:])
|
||||
else:
|
||||
minsvTElist, minsvTMlist = svdres
|
||||
|
||||
|
||||
|
||||
''' The new pretty diffracted order drawing '''
|
||||
maxlayer_reciprocal=4
|
||||
cdn = c/ math.sqrt(epsilon_b)
|
||||
bz_0 = np.array((0,0,))
|
||||
bz_K1 = np.array((1.,0))*4*np.pi/3/hexside/s3
|
||||
bz_K2 = np.array((1./2.,s3/2))*4*np.pi/3/hexside/s3
|
||||
bz_M = np.array((3./4, s3/4))*4*np.pi/3/hexside/s3
|
||||
|
||||
# reciprocal lattice basis
|
||||
B1 = 2* bz_K1 - bz_K2
|
||||
B2 = 2* bz_K2 - bz_K1
|
||||
|
||||
if svdout:
|
||||
np.savez(svdout, omega = freq, klist = klist, bzpoints = np.array([bz_0, bz_K1, bz_K2, bz_M, B1, B2]),
|
||||
uTE = svUfullTElist,
|
||||
vTE = svVfullTElist,
|
||||
sTE = svSfullTElist,
|
||||
uTM = svUfullTMlist,
|
||||
vTM = svVfullTMlist,
|
||||
sTM = svSfullTMlist,
|
||||
)
|
||||
|
||||
k2density = 100
|
||||
k0Mlist = bz_0 + (bz_M-bz_0) * np.linspace(0,1,k2density)[:,nx]
|
||||
kMK1list = bz_M + (bz_K1-bz_M) * np.linspace(0,1,k2density)[:,nx]
|
||||
kK10list = bz_K1 + (bz_0-bz_K1) * np.linspace(0,1,k2density)[:,nx]
|
||||
k0K2list = bz_0 + (bz_K2-bz_0) * np.linspace(0,1,k2density)[:,nx]
|
||||
kK2Mlist = bz_K2 + (bz_M-bz_K2) * np.linspace(0,1,k2density)[:,nx]
|
||||
k2list = np.concatenate((k0Mlist,kMK1list,kK10list,k0K2list,kK2Mlist), axis=0)
|
||||
kxmaplist = np.concatenate((np.array([0]),np.cumsum(np.linalg.norm(np.diff(k2list, axis=0), axis=-1))))
|
||||
|
||||
centers2=qpms.generate_trianglepoints(maxlayer_reciprocal, v3d = False, include_origin= True)*4*np.pi/3/hexside
|
||||
rot90 = np.array([[0,-1],[1,0]])
|
||||
centers2=np.dot(centers2,rot90)
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib
|
||||
from matplotlib.path import Path
|
||||
import matplotlib.patches as patches
|
||||
cmap = matplotlib.cm.prism
|
||||
colormax = np.amax(np.linalg.norm(centers2,axis=0))
|
||||
|
||||
|
||||
# In[ ]:
|
||||
for minN in reversed(range(svn)):
|
||||
f, axes = plt.subplots(1,3, figsize=(20,4.8))
|
||||
ax = axes[0]
|
||||
sc = ax.scatter(klist[:,0], klist[:,1], c = np.clip(np.abs(minsvTElist[:,minN]),0,1), lw=0)
|
||||
for center in centers2:
|
||||
circle=plt.Circle((center[0],center[1]),omega/cdn, facecolor='none', edgecolor=cmap(np.linalg.norm(center)/colormax),lw=0.5)
|
||||
ax.add_artist(circle)
|
||||
verts = [(math.cos(math.pi*i/3)*4*np.pi/3/hexside/s3,math.sin(math.pi*i/3)*4*np.pi/3/hexside/s3) for i in range(6 +1)]
|
||||
codes = [Path.MOVETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.CLOSEPOLY,]
|
||||
path = Path(verts, codes)
|
||||
patch = patches.PathPatch(path, facecolor='none', edgecolor='black', lw=1)
|
||||
ax.add_patch(patch)
|
||||
ax.set_xticks([])
|
||||
ax.set_yticks([])
|
||||
ax.title.set_text('E in-plane ("TE")')
|
||||
f.colorbar(sc,ax=ax)
|
||||
|
||||
|
||||
ax = axes[1]
|
||||
sc = ax.scatter(klist[:,0], klist[:,1], c = np.clip(np.abs(minsvTMlist[:,minN]),0,1), lw=0)
|
||||
for center in centers2:
|
||||
circle=plt.Circle((center[0],center[1]),omega/cdn, facecolor='none', edgecolor=cmap(np.linalg.norm(center)/colormax),lw=0.5)
|
||||
ax.add_artist(circle)
|
||||
verts = [(math.cos(math.pi*i/3)*4*np.pi/3/hexside/s3,math.sin(math.pi*i/3)*4*np.pi/3/hexside/s3) for i in range(6 +1)]
|
||||
codes = [Path.MOVETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.CLOSEPOLY,]
|
||||
path = Path(verts, codes)
|
||||
patch = patches.PathPatch(path, facecolor='none', edgecolor='black', lw=1)
|
||||
ax.add_patch(patch)
|
||||
ax.set_xticks([])
|
||||
ax.set_yticks([])
|
||||
ax.title.set_text('E perpendicular ("TM")')
|
||||
f.colorbar(sc,ax=ax)
|
||||
|
||||
ax = axes[2]
|
||||
for center in centers2:
|
||||
ax.plot(kxmaplist, np.linalg.norm(k2list-center,axis=-1)*cdn, '-', color=cmap(np.linalg.norm(center)/colormax))
|
||||
|
||||
#ax.set_xlim([np.min(kxmlarr),np.max(kxmlarr)])
|
||||
#ax.set_ylim([np.min(omegalist),np.max(omegalist)])
|
||||
xticklist = [0, kxmaplist[len(k0Mlist)-1], kxmaplist[len(k0Mlist)+len(kMK1list)-1], kxmaplist[len(k0Mlist)+len(kMK1list)+len(kK10list)-1], kxmaplist[len(k0Mlist)+len(kMK1list)+len(kK10list)+len(k0K2list)-1], kxmaplist[len(k0Mlist)+len(kMK1list)+len(kK10list)+len(k0K2list)+len(kK2Mlist)-1]]
|
||||
ax.set_xticks(xticklist)
|
||||
for xt in xticklist:
|
||||
ax.axvline(xt, ls='dotted', lw=0.3,c='k')
|
||||
ax.set_xticklabels(['Γ', 'M', 'K', 'Γ', 'K\'','M'])
|
||||
ax.axhline(omega, c='black')
|
||||
ax.set_ylim([0,5e15])
|
||||
ax2 = ax.twinx()
|
||||
ax2.set_ylim([ax.get_ylim()[0]/eV*hbar,ax.get_ylim()[1]/eV*hbar])
|
||||
|
||||
pdf.savefig(f)
|
||||
|
||||
pdf.close()
|
||||
|
||||
if scp_dest:
|
||||
subprocess.run(['scp', pdfout, scp_dest])
|
||||
if svdout:
|
||||
subprocess.run(['scp', svdout, scp_dest])
|
||||
|
||||
print(time.strftime("%H.%M:%S",time.gmtime(time.time()-begtime)))
|
|
@ -1,239 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse, re, random, string
|
||||
import subprocess
|
||||
from scipy.constants import hbar, e as eV, pi, c
|
||||
|
||||
def make_action_sharedlist(opname, listname):
|
||||
class opAction(argparse.Action):
|
||||
def __call__(self, parser, args, values, option_string=None):
|
||||
if (not hasattr(args, listname)) or getattr(args, listname) is None:
|
||||
setattr(args, listname, list())
|
||||
getattr(args,listname).append((opname, values))
|
||||
return opAction
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
#TODO? použít type=argparse.FileType('r') ?
|
||||
parser.add_argument('--TMatrix', action='store', required=True, help='Path to TMatrix file')
|
||||
#parser.add_argument('--griddir', action='store', required=True, help='Path to the directory with precalculated translation operators')
|
||||
parser.add_argument('--output_prefix', action='store', required=True, help='Prefix to the npz output (will be appended frequency, hexside and chunkno)')
|
||||
#sizepar = parser.add_mutually_exclusive_group(required=True)
|
||||
parser.add_argument('--hexside', action='store', type=float, required=True, help='Lattice hexagon size length')
|
||||
parser.add_argument('--plot_TMatrix', action='store_true', help='Visualise TMatrix on the first page of the output')
|
||||
#parser.add_argument('--SVD_output', action='store', help='Path to output singular value decomposition result')
|
||||
parser.add_argument('--maxlayer', action='store', type=int, default=100, help='How far to sum the lattice points to obtain the dispersion')
|
||||
parser.add_argument('--scp_to', action='store', metavar='N', type=str, help='SCP the output files to a given destination')
|
||||
parser.add_argument('--background_permittivity', action='store', type=float, default=1., help='Background medium relative permittivity (default 1)')
|
||||
parser.add_argument('--eVfreq', action='store', required=True, type=float, help='Frequency in eV')
|
||||
parser.add_argument('--kdensity', action='store', type=int, default=33, help='Number of k-points per x-axis segment')
|
||||
parser.add_argument('--chunklen', action='store', type=int, default=1000, help='Number of k-points per output file (default 1000)')
|
||||
parser.add_argument('--lMax', action='store', type=int, help='Override lMax from the TMatrix file')
|
||||
#TODO some more sophisticated x axis definitions
|
||||
parser.add_argument('--gaussian', action='store', type=float, metavar='σ', help='Use a gaussian envelope for weighting the interaction matrix contributions (depending on the distance), measured in unit cell lengths (?) FIxME).')
|
||||
parser.add_argument('--verbose', '-v', action='count', help='Be verbose (about computation times, mostly)')
|
||||
popgrp=parser.add_argument_group(title='Operations')
|
||||
popgrp.add_argument('--tr', dest='ops', action=make_action_sharedlist('tr', 'ops'), default=list()) # the default value for dest can be set once
|
||||
popgrp.add_argument('--tr0', dest='ops', action=make_action_sharedlist('tr0', 'ops'))
|
||||
popgrp.add_argument('--tr1', dest='ops', action=make_action_sharedlist('tr1', 'ops'))
|
||||
popgrp.add_argument('--sym', dest='ops', action=make_action_sharedlist('sym', 'ops'))
|
||||
popgrp.add_argument('--sym0', dest='ops', action=make_action_sharedlist('sym0', 'ops'))
|
||||
popgrp.add_argument('--sym1', dest='ops', action=make_action_sharedlist('sym1', 'ops'))
|
||||
#popgrp.add_argument('--mult', dest='ops', nargs=3, metavar=('INCSPEC', 'SCATSPEC', 'MULTIPLIER'), action=make_action_sharedlist('mult', 'ops'))
|
||||
#popgrp.add_argument('--mult0', dest='ops', nargs=3, metavar=('INCSPEC', 'SCATSPEC', 'MULTIPLIER'), action=make_action_sharedlist('mult0', 'ops'))
|
||||
#popgrp.add_argument('--mult1', dest='ops', nargs=3, metavar=('INCSPEC', 'SCATSPEC', 'MULTIPLIER'), action=make_action_sharedlist('mult1', 'ops'))
|
||||
popgrp.add_argument('--multl', dest='ops', nargs=3, metavar=('INCL[,INCL,...]', 'SCATL[,SCATL,...]', 'MULTIPLIER'), action=make_action_sharedlist('multl', 'ops'))
|
||||
popgrp.add_argument('--multl0', dest='ops', nargs=3, metavar=('INCL[,INCL,...]', 'SCATL[,SCATL,...]', 'MULTIPLIER'), action=make_action_sharedlist('multl0', 'ops'))
|
||||
popgrp.add_argument('--multl1', dest='ops', nargs=3, metavar=('INCL[,INCL,...]', 'SCATL[,SCATL,...]', 'MULTIPLIER'), action=make_action_sharedlist('multl1', 'ops'))
|
||||
parser.add_argument('--frequency_multiplier', action='store', type=float, default=1., help='Multiplies the frequencies in the TMatrix file by a given factor.')
|
||||
# TODO enable more flexible per-sublattice specification
|
||||
pargs=parser.parse_args()
|
||||
print(pargs)
|
||||
|
||||
maxlayer=pargs.maxlayer
|
||||
hexside=pargs.hexside
|
||||
eVfreq = pargs.eVfreq
|
||||
freq = eVfreq*eV/hbar
|
||||
verbose=pargs.verbose
|
||||
|
||||
TMatrix_file = pargs.TMatrix
|
||||
|
||||
epsilon_b = pargs.background_permittivity #2.3104
|
||||
gaussianSigma = pargs.gaussian if pargs.gaussian else None # hexside * 222 / 7
|
||||
interpfreqfactor = pargs.frequency_multiplier
|
||||
scp_dest = pargs.scp_to if pargs.scp_to else None
|
||||
kdensity = pargs.kdensity
|
||||
chunklen = pargs.chunklen
|
||||
|
||||
ops = list()
|
||||
opre = re.compile('(tr|sym|copy|multl|mult)(\d*)')
|
||||
for oparg in pargs.ops:
|
||||
opm = opre.match(oparg[0])
|
||||
if opm:
|
||||
ops.append(((opm.group(2),) if opm.group(2) else (0,1), opm.group(1), oparg[1]))
|
||||
else:
|
||||
raise # should not happen
|
||||
print(ops)
|
||||
|
||||
|
||||
# -----------------finished basic CLI parsing (except for op arguments) ------------------
|
||||
from qpms.timetrack import _time_b, _time_e
|
||||
btime=_time_b(verbose)
|
||||
|
||||
import qpms
|
||||
import numpy as np
|
||||
import os, sys, warnings, math
|
||||
from scipy import interpolate
|
||||
nx = None
|
||||
s3 = math.sqrt(3)
|
||||
|
||||
|
||||
# specifikace T-matice zde
|
||||
cdn = c/ math.sqrt(epsilon_b)
|
||||
TMatrices_orig, freqs_orig, freqs_weirdunits_orig, lMaxTM = qpms.loadScuffTMatrices(TMatrix_file)
|
||||
lMax = lMaxTM
|
||||
if pargs.lMax:
|
||||
lMax = pargs.lMax if pargs.lMax else lMaxTM
|
||||
my, ny = qpms.get_mn_y(lMax)
|
||||
nelem = len(my)
|
||||
if pargs.lMax: #force commandline specified lMax
|
||||
TMatrices_orig = TMatrices_orig[...,0:nelem,:,0:nelem]
|
||||
|
||||
TMatrices = np.array(np.broadcast_to(TMatrices_orig[:,nx,:,:,:,:],(len(freqs_orig),2,2,nelem,2,nelem)) )
|
||||
|
||||
#TMatrices[:,:,:,:,:,ny==3] *= factor13inc
|
||||
#TMatrices[:,:,:,ny==3,:,:] *= factor13scat
|
||||
xfl = qpms.xflip_tyty(lMax)
|
||||
yfl = qpms.yflip_tyty(lMax)
|
||||
zfl = qpms.zflip_tyty(lMax)
|
||||
c2rot = qpms.apply_matrix_left(qpms.yflip_yy(3),qpms.xflip_yy(3),-1)
|
||||
|
||||
reCN = re.compile('(\d*)C(\d+)')
|
||||
#TODO C nekonečno
|
||||
|
||||
for op in ops:
|
||||
if op[0] == 'all':
|
||||
targets = (0,1)
|
||||
elif isinstance(op[0],int):
|
||||
targets = (op[0],)
|
||||
else:
|
||||
targets = op[0]
|
||||
|
||||
if op[1] == 'sym':
|
||||
mCN = reCN.match(op[2]) # Fuck van Rossum for not having assignments inside expressions
|
||||
if op[2] == 'σ_z':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(zfl,qpms.apply_ndmatrix_left(zfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'σ_y':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(yfl,qpms.apply_ndmatrix_left(yfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'σ_x':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(xfl,qpms.apply_ndmatrix_left(xfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'C2': # special case of the latter
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_matrix_left(c2rot,qpms.apply_matrix_left(c2rot, TMatrices[:,t], -3),-1))/2
|
||||
elif mCN:
|
||||
rotN = int(mCN.group(2))
|
||||
TMatrix_contribs = np.empty((rotN,TMatrices.shape[0],2,nelem,2,nelem), dtype=np.complex_)
|
||||
for t in targets:
|
||||
for i in range(rotN):
|
||||
rotangle = 2*np.pi*i / rotN
|
||||
rot = qpms.WignerD_yy_fromvector(lMax,np.array([0,0,rotangle]))
|
||||
rotinv = qpms.WignerD_yy_fromvector(lMax,np.array([0,0,-rotangle]))
|
||||
TMatrix_contribs[i] = qpms.apply_matrix_left(rot,qpms.apply_matrix_left(rotinv, TMatrices[:,t], -3),-1)
|
||||
TMatrices[:,t] = np.sum(TMatrix_contribs, axis=0) / rotN
|
||||
else:
|
||||
raise
|
||||
elif op[1] == 'tr':
|
||||
mCN = reCN.match(op[2]) # Fuck van Rossum for not having assignments inside expressions
|
||||
if op[2] == 'σ_z':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(zfl,qpms.apply_ndmatrix_left(zfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'σ_y':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(yfl,qpms.apply_ndmatrix_left(yfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'σ_x':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(xfl,qpms.apply_ndmatrix_left(xfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'C2':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_matrix_left(c2rot,qpms.apply_matrix_left(c2rot, TMatrices[:,t], -3),-1)
|
||||
elif mCN:
|
||||
rotN = int(mCN.group(2))
|
||||
power = int(mCN.group(1)) if mCN.group(1) else 1
|
||||
TMatrix_contribs = np.empty((rotN,TMatrices.shape[0],2,nelem,2,nelem), dtype=np.complex_)
|
||||
for t in targets:
|
||||
rotangle = 2*np.pi*power/rotN
|
||||
rot = qpms.WignerD_yy_fromvector(lMax, np.array([0,0,rotangle]))
|
||||
rotinv = qpms.WignerD_yy_fromvector(lMax, np.array([0,0,-rotangle]))
|
||||
TMatrices[:,t] = qpms.apply_matrix_left(rot, qpms.apply_matrix_left(rotinv, TMatrices[:,t], -3),-1)
|
||||
else:
|
||||
raise
|
||||
elif op[1] == 'copy':
|
||||
raise # not implemented
|
||||
elif op[1] == 'mult':
|
||||
raise # not implemented
|
||||
elif op[1] == 'multl':
|
||||
incy = np.full((nelem,), False, dtype=bool)
|
||||
for incl in op[2][0].split(','):
|
||||
l = int(incl)
|
||||
incy += (l == ny)
|
||||
scaty = np.full((nelem,), False, dtype=bool)
|
||||
for scatl in op[2][1].split(','):
|
||||
l = int(scatl)
|
||||
scaty += (l == ny)
|
||||
for t in targets:
|
||||
TMatrices[np.ix_(np.arange(TMatrices.shape[0]),np.array([t]),np.array([0,1]),scaty,np.array([0,1]),incy)] *= float(op[2][2])
|
||||
else:
|
||||
raise #unknown operation; should not happen
|
||||
|
||||
TMatrices_interp = interpolate.interp1d(freqs_orig*interpfreqfactor, TMatrices, axis=0, kind='linear',fill_value="extrapolate")
|
||||
|
||||
klist_full = qpms.generate_trianglepoints(kdensity, v3d=True, include_origin=True)*3*math.pi/(3*kdensity*hexside)
|
||||
TMatrices_om = TMatrices_interp(freq)
|
||||
|
||||
chunkn = math.ceil(klist_full.shape[0] / chunklen)
|
||||
|
||||
if verbose:
|
||||
print('Evaluating %d k-points in %d chunks' % (klist_full.shape[0], chunkn), file = sys.stderr)
|
||||
sys.stderr.flush()
|
||||
|
||||
metadata = np.array({
|
||||
'lMax' : lMax,
|
||||
'maxlayer' : maxlayer,
|
||||
'gaussianSigma' : gaussianSigma,
|
||||
'epsilon_b' : epsilon_b,
|
||||
'hexside' : hexside,
|
||||
'chunkn' : chunkn,
|
||||
'TMatrix_file' : TMatrix_file,
|
||||
'ops' : ops,
|
||||
})
|
||||
|
||||
for chunki in range(chunkn):
|
||||
svdout = '%s_%dnm_%.4f_c%03d.npz' % (pargs.output_prefix, hexside/1e-9, eVfreq, chunki)
|
||||
|
||||
klist = klist_full[chunki * chunklen : (chunki + 1) * chunklen]
|
||||
|
||||
svdres = qpms.hexlattice_zsym_getSVD(lMax=lMax, TMatrices_om=TMatrices_om, epsilon_b=epsilon_b, hexside=hexside, maxlayer=maxlayer,
|
||||
omega=freq, klist=klist, gaussianSigma=gaussianSigma, onlyNmin=False, verbose=verbose)
|
||||
|
||||
#((svUfullTElist, svSfullTElist, svVfullTElist), (svUfullTMlist, svSfullTMlist, svVfullTMlist)) = svdres
|
||||
|
||||
np.savez(svdout, omega = freq, klist = klist,
|
||||
metadata=metadata,
|
||||
uTE = svdres[0][0],
|
||||
vTE = svdres[0][2],
|
||||
sTE = svdres[0][1],
|
||||
uTM = svdres[1][0],
|
||||
vTM = svdres[1][2],
|
||||
sTM = svdres[1][1],
|
||||
|
||||
)
|
||||
svdres=None
|
||||
|
||||
if scp_dest:
|
||||
if svdout:
|
||||
subprocess.run(['scp', svdout, scp_dest])
|
||||
|
||||
_time_e(btime, verbose)
|
||||
#print(time.strftime("%H.%M:%S",time.gmtime(time.time()-begtime)))
|
|
@ -0,0 +1,719 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import numpy as np\n",
|
||||
"import qpms\n",
|
||||
"import warnings\n",
|
||||
"from qpms.cybspec import BaseSpec\n",
|
||||
"from qpms.cytmatrices import CTMatrix, TMatrixGenerator, TMatrixInterpolator\n",
|
||||
"from qpms.qpms_c import Particle, pgsl_ignore_error\n",
|
||||
"from qpms.cymaterials import EpsMu, EpsMuGenerator, LorentzDrudeModel, lorentz_drude\n",
|
||||
"from qpms.cycommon import DebugFlags, dbgmsg_enable\n",
|
||||
"from qpms import FinitePointGroup, ScatteringSystem, BesselType, eV, hbar\n",
|
||||
"import scipy.constants as sci\n",
|
||||
"eh = eV/hbar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#TODO\n",
|
||||
"period = 520e-9\n",
|
||||
"a1 = np.array([0,period]) \n",
|
||||
"a2 = np.array([period,0])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#Particle positions\n",
|
||||
"orig_x = [0]\n",
|
||||
"orig_y = [0]\n",
|
||||
"orig_xy = np.stack(np.meshgrid(orig_x,orig_y),axis=-1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"period = 0.52\n",
|
||||
"refractive_index = 1.52 # for background medium\n",
|
||||
"height = 50e-9 # Particle height\n",
|
||||
"radius = 50e-9 # Particle radius\n",
|
||||
"medium = EpsMu(refractive_index**2) # non-lossy background medium with constant refr. index #OK\n",
|
||||
"# global symmetry group of the system\n",
|
||||
"#sym = FinitePointGroup(point_group_info['D4h'])\n",
|
||||
"omega = 1.58*eh\n",
|
||||
"metal = lorentz_drude['Ag']\n",
|
||||
"kx_lim = np.array([-0.2, 0.2], dtype=float)\n",
|
||||
"N=501"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(7.59633723939313, 8.305328715069821, 7.94387469344152, 8.001475225494097)"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"omega_scuff_min=1.5*eh/3e14\n",
|
||||
"omega_scuff_max=1.64*eh/3e14\n",
|
||||
"omega_scuff=omega/3e14\n",
|
||||
"omega_scuff_slr=(2*np.pi*sci.c/(1.52*0.52e-6))/3e14\n",
|
||||
"omega_scuff_min, omega_scuff_max, omega_scuff_slr, omega_scuff"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"bspec = BaseSpec(lMax = 1)\n",
|
||||
"\n",
|
||||
"tmfile_scuffOld = '/home/javier/tmatrices/sphereAg_50nm_oldScuff.TMatrix'\n",
|
||||
"tmfile_scuffNew = '/home/javier/tmatrices/sphere50nm_newScuff.TMatrix'\n",
|
||||
"interp_old = TMatrixInterpolator(tmfile_scuffOld, bspec, atol=1e-8) \n",
|
||||
"interp_new = TMatrixInterpolator(tmfile_scuffNew, bspec, atol=1e-8) \n",
|
||||
"tmscuff_not_fixed = interp_old(omega)\n",
|
||||
"tmscuff_bugfixed = interp_new(omega)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"tmgen = TMatrixGenerator.sphere(medium, metal, radius)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"tmgen_omega=tmgen(bspec,omega)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[-0.07824951+0.25215549j, 0. +0.j , 0. +0.j , 0. +0.j , 0. +0.j , 0. +0.j ],\n",
|
||||
" [ 0. +0.j , -0.07824951+0.25215549j, 0. +0.j , 0. +0.j , 0. +0.j , 0. +0.j ],\n",
|
||||
" [ 0. +0.j , 0. +0.j , -0.07824951+0.25215549j, 0. +0.j , 0. +0.j , 0. +0.j ],\n",
|
||||
" [ 0. +0.j , 0. +0.j , 0. +0.j , -0.00083788-0.01420874j, 0. +0.j , 0. +0.j ],\n",
|
||||
" [ 0. +0.j , 0. +0.j , 0. +0.j , 0. +0.j , -0.00083788-0.01420874j, 0. +0.j ],\n",
|
||||
" [ 0. +0.j , 0. +0.j , 0. +0.j , 0. +0.j , 0. +0.j , -0.00083788-0.01420874j]])"
|
||||
]
|
||||
},
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tmgen_omega.as_ndarray() # T-Matrix from generator"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[-4.70886671e-03+1.79440815e-02j, 1.60098226e-13+4.20092462e-13j, 2.26455777e-07+3.98932962e-07j, -2.13258227e-14-6.01930824e-14j, 7.66251504e-08-1.32539814e-08j,\n",
|
||||
" -7.76488937e-14+1.08532726e-13j],\n",
|
||||
" [-4.41531068e-13+9.81757019e-14j, -4.70582367e-03+1.79389513e-02j, -1.60702588e-13-4.19762769e-13j, 6.32372612e-08+4.71302619e-08j, -2.36039655e-14+1.00983241e-13j,\n",
|
||||
" 7.76590838e-08-1.38092126e-08j],\n",
|
||||
" [-4.58579591e-07-7.49053314e-09j, 4.41175187e-13-9.87457125e-14j, -4.70886672e-03+1.79440815e-02j, 2.13790755e-14+1.31812722e-13j, 6.25535562e-08+4.61875295e-08j,\n",
|
||||
" 4.59276044e-14-4.47400043e-14j],\n",
|
||||
" [ 4.93366461e-14-4.29235249e-14j, -6.94450011e-09-1.60278760e-08j, -7.79609985e-14+1.07845028e-13j, -3.03166095e-05-2.01474828e-03j, -2.39253108e-13-1.34944425e-13j,\n",
|
||||
" 1.16328171e-08+6.36863105e-09j],\n",
|
||||
" [ 8.21008790e-09-1.53591010e-08j, -2.36580203e-14+1.00878213e-13j, -5.41800099e-09-1.65573897e-08j, 2.26431323e-13-1.55248143e-13j, -3.03231670e-05-2.01493037e-03j,\n",
|
||||
" 2.38800352e-13+1.35401679e-13j],\n",
|
||||
" [ 2.18731933e-14+1.31428484e-13j, 7.13657440e-09-1.65412452e-08j, -2.48667583e-14-6.12974376e-14j, -1.11447700e-08+7.19733229e-09j, -2.26916383e-13+1.54810715e-13j,\n",
|
||||
" -3.03166170e-05-2.01474828e-03j]])"
|
||||
]
|
||||
},
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tmscuff_not_fixed.as_ndarray() # T-Matrix of not fixed version of Scuff-EM"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[-9.43033280e-02+3.59361755e-01j, 3.20658236e-12+8.41416904e-12j, 5.13892659e-06+8.57797510e-06j, -4.28949536e-13-1.20456867e-12j, 1.41239218e-06-2.46862181e-07j,\n",
|
||||
" -1.55480479e-12+2.17400571e-12j],\n",
|
||||
" [-8.84386127e-12+1.96169624e-12j, -9.42395846e-02+3.59248336e-01j, -3.22166474e-12-8.40342496e-12j, 1.16868119e-06+8.68484583e-07j, -4.72874254e-13+2.02296639e-12j,\n",
|
||||
" 1.43308826e-06-2.58864855e-07j],\n",
|
||||
" [-9.99885677e-06+6.63229466e-08j, 8.83605486e-12-1.97841571e-12j, -9.43033282e-02+3.59361755e-01j, 4.27888728e-13+2.63976219e-12j, 1.15544356e-06+8.48824647e-07j,\n",
|
||||
" 9.21093604e-13-8.94225073e-13j],\n",
|
||||
" [ 9.85267406e-13-8.59818272e-13j, -1.43866720e-06+2.57952214e-07j, -1.56233879e-12+2.15974773e-12j, -6.07143255e-04-4.03488631e-02j, -4.79139425e-12-2.70322093e-12j,\n",
|
||||
" 1.52945653e-07+8.36194839e-08j],\n",
|
||||
" [-1.15196465e-06-8.46913318e-07j, -4.73514628e-13+2.02574744e-12j, -1.40806670e-06+2.47097086e-07j, 4.53481568e-12-3.10854698e-12j, -6.07256494e-04-4.03513114e-02j,\n",
|
||||
" 4.78231690e-12+2.71099900e-12j],\n",
|
||||
" [ 4.39050064e-13+2.63269196e-12j, -1.17350730e-06-8.70822943e-07j, -4.95069921e-13-1.22744130e-12j, -1.44529174e-07+9.78280211e-08j, -4.54412580e-12+3.10101417e-12j,\n",
|
||||
" -6.07143303e-04-4.03488631e-02j]])"
|
||||
]
|
||||
},
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tmscuff_bugfixed.as_ndarray() # T-Matrix of FIXED version of Scuff-EM"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(matrix([[-9.43033280e-02+3.59361755e-01j, 3.20658236e-12+8.41416904e-12j],\n",
|
||||
" [-8.84386127e-12+1.96169624e-12j, -9.42395846e-02+3.59248336e-01j]]),\n",
|
||||
" matrix([[-9.43033280e-02-3.59361755e-01j, -8.84386127e-12-1.96169624e-12j],\n",
|
||||
" [ 3.20658236e-12-8.41416904e-12j, -9.42395846e-02-3.59248336e-01j]]))"
|
||||
]
|
||||
},
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#I play around with the different operations so everything is correct\n",
|
||||
"tmscuffnew = tmscuff_bugfixed.as_ndarray()\n",
|
||||
"tmscuffnew_mat = np.asmatrix(tmscuffnew)\n",
|
||||
"tmscuffnew_dag = tmscuffnew_mat.getH()\n",
|
||||
"tmscuffnew_mat[0:2,0:2], tmscuffnew_dag[0:2,0:2]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(matrix([[1, 0],\n",
|
||||
" [9, 4]]), matrix([[4, 9],\n",
|
||||
" [0, 1]]))"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"A = np.matrix([[0,1],[2,3]])\n",
|
||||
"B = np.matrix([[3,2],[1,0]])\n",
|
||||
"AB = np.dot(A,B)\n",
|
||||
"BA = np.dot(B,A)\n",
|
||||
"AB,BA"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"sum1new = np.dot(tmscuffnew_dag,tmscuffnew) #is this the right order? Regarding the above, yes it is.\n",
|
||||
"sum2new = 0.5*tmscuffnew.__add__(tmscuffnew_dag) "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"powermatrix_scuffnew = sum1new.__add__(sum2new) #powermatrix for bugfixed scuff"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#Power matrix for NOT bugfixed scuff\n",
|
||||
"tmscuffold = tmscuff_not_fixed.as_ndarray()\n",
|
||||
"tmscuffold_mat = np.asmatrix(tmscuffold)\n",
|
||||
"tmscuffold_dag = tmscuffold_mat.getH()\n",
|
||||
"sum1old = np.dot(tmscuffold_dag,tmscuffold) #is this the right order? Regarding the above, yes it is.\n",
|
||||
"sum2old = 0.5*tmscuffold.__add__(tmscuffold_dag)\n",
|
||||
"\n",
|
||||
"powermatrix_scuffold = sum1old.__add__(sum2old) "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#Power matrix for T matrix generator\n",
|
||||
"tmscuffgen = tmgen_omega.as_ndarray()\n",
|
||||
"tmscuffgen_mat = np.asmatrix(tmscuffgen)\n",
|
||||
"tmscuffgen_dag = tmscuffgen_mat.getH()\n",
|
||||
"sum1gen = np.dot(tmscuffgen_dag,tmscuffgen) #is this the right order? Regarding the above, yes it is.\n",
|
||||
"sum2gen = 0.5*tmscuffgen.__add__(tmscuffgen_dag)\n",
|
||||
"\n",
|
||||
"powermatrix_scuffgen = sum1gen.__add__(sum2gen) "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((-0.008544129580638216+0j),\n",
|
||||
" (-0.008544129580638216+0j),\n",
|
||||
" (-0.008544129580638216+0j),\n",
|
||||
" (-0.0006352854997266949+0j),\n",
|
||||
" (-0.0006352854997266949+0j),\n",
|
||||
" (-0.0006352854997266949+0j))"
|
||||
]
|
||||
},
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#Power matrix of generator is diagonal and all its eigenvalues are negative:\n",
|
||||
"powermatrix_scuffgen[0,0], powermatrix_scuffgen[1,1], powermatrix_scuffgen[2,2], powermatrix_scuffgen[3,3], powermatrix_scuffgen[4,4], powermatrix_scuffgen[5,5]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((0.04373066071852283+0j),\n",
|
||||
" (0.04370088172427582+0j),\n",
|
||||
" (0.043730660553373296+0j),\n",
|
||||
" (0.001021256123757952+0j),\n",
|
||||
" (0.0010213406041430792+0j),\n",
|
||||
" (0.0010212560750220145+0j))"
|
||||
]
|
||||
},
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"powermatrix_scuffnew[0,0], powermatrix_scuffnew[1,1], powermatrix_scuffnew[2,2], powermatrix_scuffnew[3,3], powermatrix_scuffnew[4,4], powermatrix_scuffnew[5,5]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((-0.004364703222422517+0j),\n",
|
||||
" (-0.004361872918812184+0j),\n",
|
||||
" (-0.004364703232328262+0j),\n",
|
||||
" (-2.6256479824067564e-05+0j),\n",
|
||||
" (-2.6262303053141142e-05+0j),\n",
|
||||
" (-2.6256487319428013e-05+0j))"
|
||||
]
|
||||
},
|
||||
"execution_count": 20,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"powermatrix_scuffold[0,0], powermatrix_scuffold[1,1], powermatrix_scuffold[2,2], powermatrix_scuffold[3,3], powermatrix_scuffold[4,4], powermatrix_scuffold[5,5]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((-10.019160178833705-0j),\n",
|
||||
" (-10.018834234211564-0j),\n",
|
||||
" (-10.019160118257586-0j),\n",
|
||||
" (-38.895393845668316-0j),\n",
|
||||
" (-38.88998623145963-0j),\n",
|
||||
" (-38.89538088616882-0j))"
|
||||
]
|
||||
},
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#So! There is a fixed factor between the N/M elements of Scuff new and old:\n",
|
||||
"powermatrix_scuffnew[0,0]/powermatrix_scuffold[0,0], powermatrix_scuffnew[1,1]/powermatrix_scuffold[1,1], powermatrix_scuffnew[2,2]/powermatrix_scuffold[2,2], powermatrix_scuffnew[3,3]/powermatrix_scuffold[3,3], powermatrix_scuffnew[4,4]/powermatrix_scuffold[4,4], powermatrix_scuffnew[5,5]/powermatrix_scuffold[5,5]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((-5.118211317583541-0j),\n",
|
||||
" (-5.11472600126595-0j),\n",
|
||||
" (-5.118211298254535-0j),\n",
|
||||
" (-1.6075545942687262-0j),\n",
|
||||
" (-1.6076875744566317-0j),\n",
|
||||
" (-1.60755451755371-0j))"
|
||||
]
|
||||
},
|
||||
"execution_count": 23,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#And there is a fixed factor for new / generated as well! (hence also for old / generated)\n",
|
||||
"powermatrix_scuffnew[0,0]/powermatrix_scuffgen[0,0], powermatrix_scuffnew[1,1]/powermatrix_scuffgen[1,1], powermatrix_scuffnew[2,2]/powermatrix_scuffgen[2,2], powermatrix_scuffnew[3,3]/powermatrix_scuffgen[3,3], powermatrix_scuffnew[4,4]/powermatrix_scuffgen[4,4], powermatrix_scuffnew[5,5]/powermatrix_scuffgen[5,5]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((-1.60755451755371-0j), (-2.557363000632975+0j))"
|
||||
]
|
||||
},
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"powermatrix_scuffnew[5,5]/powermatrix_scuffgen[5,5], powermatrix_scuffnew[1,1]/powermatrix_scuffgen[1,1]/2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((1.599227713011597e-16-0j),\n",
|
||||
" (8.902299490051238e-14+0j),\n",
|
||||
" (1.504486797691096e-21-0j))"
|
||||
]
|
||||
},
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#Let's also calculate the determinants\n",
|
||||
"detnew = powermatrix_scuffnew[0,0]*powermatrix_scuffnew[1,1]*powermatrix_scuffnew[2,2]*powermatrix_scuffnew[3,3]*powermatrix_scuffnew[4,4]*powermatrix_scuffnew[5,5]\n",
|
||||
"detold = powermatrix_scuffold[0,0]*powermatrix_scuffold[1,1]*powermatrix_scuffold[2,2]*powermatrix_scuffold[3,3]*powermatrix_scuffold[4,4]*powermatrix_scuffold[5,5]\n",
|
||||
"detgen = powermatrix_scuffgen[0,0]*powermatrix_scuffgen[1,1]*powermatrix_scuffgen[2,2]*powermatrix_scuffgen[3,3]*powermatrix_scuffgen[4,4]*powermatrix_scuffgen[5,5]\n",
|
||||
"detgen, detnew, detold"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((1.5992277130116025e-16+0j),\n",
|
||||
" (8.902299447416401e-14+2.6128569373609595e-39j),\n",
|
||||
" (1.504486701753944e-21-2.892571608172536e-45j))"
|
||||
]
|
||||
},
|
||||
"execution_count": 23,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"np.linalg.det(powermatrix_scuffgen), np.linalg.det(powermatrix_scuffnew), np.linalg.det(powermatrix_scuffold)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#We try to normalize the power matrix elements for each case with the corresponding determinants."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((-53426597795433.88+0j),\n",
|
||||
" (-53426597795433.88+0j),\n",
|
||||
" (-53426597795433.88+0j),\n",
|
||||
" (-3972451793812.1055+0j),\n",
|
||||
" (-3972451793812.1055+0j),\n",
|
||||
" (-3972451793812.1055+0j))"
|
||||
]
|
||||
},
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#T-matrix generator: \n",
|
||||
"powermatrix_scuffgen[0,0]/detgen, powermatrix_scuffgen[1,1]/detgen, powermatrix_scuffgen[2,2]/detgen, powermatrix_scuffgen[3,3]/detgen, powermatrix_scuffgen[4,4]/detgen, powermatrix_scuffgen[5,5]/detgen "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 26,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((-2.901124309712079e+18+0j),\n",
|
||||
" (-2.899243067806416e+18+0j),\n",
|
||||
" (-2.901124316296214e+18+0j),\n",
|
||||
" (-1.7452117136795634e+16+0j),\n",
|
||||
" (-1.7455987711853198e+16+0j),\n",
|
||||
" (-1.7452122118800434e+16+0j))"
|
||||
]
|
||||
},
|
||||
"execution_count": 26,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#Not bugfixed Scuff-EM: \n",
|
||||
"powermatrix_scuffold[0,0]/detold, powermatrix_scuffold[1,1]/detold, powermatrix_scuffold[2,2]/detold, powermatrix_scuffold[3,3]/detold, powermatrix_scuffold[4,4]/detold, powermatrix_scuffold[5,5]/detold "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 27,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((491228819782.9563+0j),\n",
|
||||
" (490894310768.96173+0j),\n",
|
||||
" (491228817927.8229+0j),\n",
|
||||
" (11471823936.043226+0j),\n",
|
||||
" (11472772908.667904+0j),\n",
|
||||
" (11471823388.58987+0j))"
|
||||
]
|
||||
},
|
||||
"execution_count": 27,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#New Scuff-EM: \n",
|
||||
"powermatrix_scuffnew[0,0]/detnew, powermatrix_scuffnew[1,1]/detnew, powermatrix_scuffnew[2,2]/detnew, powermatrix_scuffnew[3,3]/detnew, powermatrix_scuffnew[4,4]/detnew, powermatrix_scuffnew[5,5]/detnew "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 28,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#It might make more sense to renormalize the electric and magnetic parts of the power matrices separately:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 29,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((13698.226641508763-0j),\n",
|
||||
" (13698.226641508763-0j),\n",
|
||||
" (13698.226641508763-0j),\n",
|
||||
" (2477776.413504498-0j),\n",
|
||||
" (2477776.413504498-0j),\n",
|
||||
" (2477776.413504498-0j))"
|
||||
]
|
||||
},
|
||||
"execution_count": 29,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#T-matrix generator:\n",
|
||||
"detgen_el = powermatrix_scuffgen[0,0]*powermatrix_scuffgen[1,1]*powermatrix_scuffgen[2,2]\n",
|
||||
"detgen_mag = powermatrix_scuffgen[3,3]*powermatrix_scuffgen[4,4]*powermatrix_scuffgen[5,5]\n",
|
||||
"powermatrix_scuffgen[0,0]/detgen_el, powermatrix_scuffgen[1,1]/detgen_el, powermatrix_scuffgen[2,2]/detgen_el, powermatrix_scuffgen[3,3]/detgen_mag, powermatrix_scuffgen[4,4]/detgen_mag, powermatrix_scuffgen[5,5]/detgen_mag "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 30,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((52525.751093170744-0j),\n",
|
||||
" (52491.69062780147-0j),\n",
|
||||
" (52525.75121237855-0j),\n",
|
||||
" (1450208903.6280527-0j),\n",
|
||||
" (1450530534.6580672-0j),\n",
|
||||
" (1450209317.614944-0j))"
|
||||
]
|
||||
},
|
||||
"execution_count": 30,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#NOT bugfixed Scuff-EM:\n",
|
||||
"detold_el = powermatrix_scuffold[0,0]*powermatrix_scuffold[1,1]*powermatrix_scuffold[2,2]\n",
|
||||
"detold_mag = powermatrix_scuffold[3,3]*powermatrix_scuffold[4,4]*powermatrix_scuffold[5,5]\n",
|
||||
"powermatrix_scuffold[0,0]/detold_el, powermatrix_scuffold[1,1]/detold_el, powermatrix_scuffold[2,2]/detold_el, powermatrix_scuffold[3,3]/detold_mag, powermatrix_scuffold[4,4]/detold_mag, powermatrix_scuffold[5,5]/detold_mag "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 31,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((523.2675016470721+0j),\n",
|
||||
" (522.9111754524715+0j),\n",
|
||||
" (523.2674996709441+0j),\n",
|
||||
" (958726.5381294343+0j),\n",
|
||||
" (958805.8459399715+0j),\n",
|
||||
" (958726.4923775065+0j))"
|
||||
]
|
||||
},
|
||||
"execution_count": 31,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#Bugfixed Scuff-EM:\n",
|
||||
"detnew_el = powermatrix_scuffnew[0,0]*powermatrix_scuffnew[1,1]*powermatrix_scuffnew[2,2]\n",
|
||||
"detnew_mag = powermatrix_scuffnew[3,3]*powermatrix_scuffnew[4,4]*powermatrix_scuffnew[5,5]\n",
|
||||
"powermatrix_scuffnew[0,0]/detnew_el, powermatrix_scuffnew[1,1]/detnew_el, powermatrix_scuffnew[2,2]/detnew_el, powermatrix_scuffnew[3,3]/detnew_mag, powermatrix_scuffnew[4,4]/detnew_mag, powermatrix_scuffnew[5,5]/detnew_mag "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
|
@ -0,0 +1,362 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
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.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)')
|
||||
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("-g", "--save-gradually", action='store_true', help="saves the partial result after computing each irrep")
|
||||
ap.add_argument("-S", "--symmetry-adapted", default=None, help="Use a symmetry-adapted basis of a given point group instead of individual spherical harmonics")
|
||||
ap.add_argument("-d", "--ccd-distance", type=float, default=math.nan, help='Far-field "CCD" distance from the sample')
|
||||
ap.add_argument("-D", "--ccd-size", type=float, default=math.nan, help='Far-field "CCD" width and heighth')
|
||||
ap.add_argument("-R", "--ccd-resolution", type=int, default=101, help='Far-field "CCD" resolution')
|
||||
ap.add_argument("--xslice", default={None:None}, nargs=2,
|
||||
action=make_dict_action(argtype=sslice, postaction='append', first_is_key=True),
|
||||
)
|
||||
ap.add_argument("--yslice", default={None:None}, nargs=2,
|
||||
action=make_dict_action(argtype=sslice, postaction='append', first_is_key=True),
|
||||
)
|
||||
|
||||
|
||||
#ap.add_argument("--irrep", type=str, default="none", help="Irrep subspace (irrep index from 0 to 7, irrep label, or 'none' for no irrep decomposition")
|
||||
|
||||
|
||||
a=ap.parse_args()
|
||||
|
||||
import logging
|
||||
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
|
||||
|
||||
Nx, Ny = a.size
|
||||
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)
|
||||
logging.info("Default file prefix: %s" % defaultprefix)
|
||||
|
||||
import numpy as np
|
||||
import qpms
|
||||
from qpms.cybspec import BaseSpec
|
||||
from qpms.cytmatrices import CTMatrix, TMatrixGenerator
|
||||
from qpms.qpms_c import Particle, qpms_library_version
|
||||
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
|
||||
|
||||
# Check slice ranges and generate all corresponding combinations
|
||||
slicepairs = []
|
||||
slicelabels = set(a.xslice.keys()) | set(a.yslice.keys())
|
||||
for label in slicelabels:
|
||||
rowslices = a.xslice.get(label, None)
|
||||
colslices = a.yslice.get(label, None)
|
||||
# TODO check validity of the slices.
|
||||
if rowslices is None:
|
||||
rowslices = [slice(None, None, None)]
|
||||
if colslices is None:
|
||||
colslices = [slice(None, None, None)]
|
||||
for rs in rowslices:
|
||||
for cs in colslices:
|
||||
slicepairs.append((rs, cs))
|
||||
|
||||
def realdipfieldlabels(yp):
|
||||
if yp == 0: return 'x'
|
||||
if yp == 1: return 'y'
|
||||
if yp == 2: return 'z'
|
||||
raise ValueError
|
||||
def realdipfields(vecgrid, yp):
|
||||
if yp == 1:
|
||||
return vecgrid[...,0] + vecgrid[...,2]
|
||||
if yp == 0:
|
||||
return -1j*(vecgrid[...,0] - vecgrid[...,2])
|
||||
if yp == 2:
|
||||
return vecgrid[...,1]
|
||||
raise ValueError
|
||||
|
||||
def float_nicestr(x, tol=1e-5):
|
||||
x = float(x)
|
||||
if .5**2 - abs(x) < tol:
|
||||
return(("-" if x < 0 else '+') + "2^{-2}")
|
||||
else:
|
||||
return "%+.3g" % x
|
||||
|
||||
def cplx_nicestr(x, tol=1e-5):
|
||||
x = complex(x)
|
||||
if x == 0:
|
||||
return '0'
|
||||
ret = ""
|
||||
if x.real:
|
||||
ret = ret + float_nicestr(x.real, tol)
|
||||
if x.imag:
|
||||
ret = ret + float_nicestr(x.imag, tol) + 'i'
|
||||
if x.real and x.imag:
|
||||
return '(' + ret + ')'
|
||||
else:
|
||||
return ret
|
||||
|
||||
def cleanarray(a, atol=1e-10, copy=True):
|
||||
a = np.array(a, copy=copy)
|
||||
sieve = abs(a.real) < atol
|
||||
a[sieve] = 1j * a[sieve].imag
|
||||
sieve = abs(a.imag) < atol
|
||||
a[sieve] = a[sieve].real
|
||||
return a
|
||||
|
||||
def nicerot(a, atol=1e-10, copy=True): #gives array a "nice" phase
|
||||
a = np.array(a, copy=copy)
|
||||
i = np.argmax(abs(a))
|
||||
a = a / a[i] * abs(a[i])
|
||||
return a
|
||||
|
||||
dbgmsg_enable(DebugFlags.INTEGRATION)
|
||||
|
||||
#Particle positions
|
||||
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
|
||||
|
||||
orig_xy = np.stack(np.meshgrid(orig_x, orig_y), axis = -1)
|
||||
|
||||
|
||||
omega = ap.omega
|
||||
|
||||
bspec = BaseSpec(lMax = a.lMax)
|
||||
medium = EpsMuGenerator(ap.background_epsmu)
|
||||
particles= [Particle(orig_xy[i], ap.tmgen, bspec) for i in np.ndindex(orig_xy.shape[:-1])]
|
||||
|
||||
sym = FinitePointGroup(point_group_info['D2h'])
|
||||
ss, ssw = ScatteringSystem.create(particles=particles, medium=medium, omega=omega, sym=sym)
|
||||
|
||||
wavenumber = ap.background_epsmu.k(omega) # Currently, ScatteringSystem does not "remember" frequency nor wavenumber
|
||||
|
||||
# Mapping between ss particles and grid positions
|
||||
positions = ss.positions
|
||||
xpositions = np.unique(positions[:,0])
|
||||
assert(len(xpositions) == Nx)
|
||||
ypositions = np.unique(positions[:,1])
|
||||
assert(len(ypositions == Ny))
|
||||
# particle positions as integer indices
|
||||
posmap = np.empty((positions.shape[0],2), dtype=int)
|
||||
invposmap = np.empty((Nx, Ny), dtype=int)
|
||||
for i, pos in enumerate(positions):
|
||||
posmap[i,0] = np.searchsorted(xpositions, positions[i,0])
|
||||
posmap[i,1] = np.searchsorted(ypositions, positions[i,1])
|
||||
invposmap[posmap[i,0], posmap[i, 1]] = i
|
||||
|
||||
def fullvec2grid(fullvec, swapxy=False):
|
||||
arr = np.empty((Nx,Ny,nelem), dtype=complex)
|
||||
for pi, offset in enumerate(ss.fullvec_poffsets):
|
||||
ix, iy = posmap[pi]
|
||||
arr[ix, iy] = fullvec[offset:offset+nelem]
|
||||
return np.swapaxes(arr, 0, 1) if swapxy else arr
|
||||
|
||||
|
||||
outfile_tmp = defaultprefix + ".tmp" if a.output is None else a.output + ".tmp"
|
||||
|
||||
nelem = len(bspec)
|
||||
phases = np.exp(1j*np.dot(ss.positions[:,:2], np.array(a.wavevector)))
|
||||
driving_full = np.zeros((nelem, ss.fecv_size),dtype=complex)
|
||||
if a.symmetry_adapted is not None:
|
||||
ss1, ssw1 = ScatteringSystem.create(particles=[Particle((0,0,0), ap.tmgen, bspec)], medium=medium, omega=omega,
|
||||
sym=FinitePointGroup(point_group_info[a.symmetry_adapted]))
|
||||
fvcs1 = np.empty((nelem, nelem), dtype=complex)
|
||||
y = 0
|
||||
iris1 = []
|
||||
for iri1 in range(ss1.nirreps):
|
||||
for j in range(ss1.saecv_sizes[iri1]):
|
||||
pvc1 = np.zeros((ss1.saecv_sizes[iri1],), dtype=complex)
|
||||
pvc1[j] = 1
|
||||
fvcs1[y] = ss1.unpack_vector(pvc1, iri1)
|
||||
fvcs1[y] = cleanarray(nicerot(fvcs1[y], copy=False), copy=False)
|
||||
driving_full[y] = (phases[:, None] * fvcs1[y][None,:]).flatten()
|
||||
y += 1
|
||||
iris1.append(iri1)
|
||||
iris1 = np.array(iris1)
|
||||
else:
|
||||
for y in range(nelem):
|
||||
driving_full[y,y::nelem] = phases
|
||||
|
||||
|
||||
# Apply the driving on the specified slices only
|
||||
nsp = len(slicepairs)
|
||||
driving_full_sliced = np.zeros((nsp,) + driving_full.shape, dtype=complex)
|
||||
p1range = np.arange(nelem)
|
||||
for spi in range(nsp):
|
||||
xs, ys = slicepairs[spi]
|
||||
driven_pi = invposmap[xs, ys].flatten()
|
||||
driven_y = ((driven_pi * nelem)[:,None] + p1range[None,:]).flatten()
|
||||
driving_full_sliced[spi][:, driven_y] = driving_full[:, driven_y]
|
||||
|
||||
scattered_full = np.zeros((nsp, nelem, ss.fecv_size),dtype=complex)
|
||||
scattered_ir = [None for iri in range(ss.nirreps)]
|
||||
|
||||
ir_contained = np.ones((nsp, nelem, ss.nirreps), dtype=bool)
|
||||
|
||||
for iri in range(ss.nirreps):
|
||||
logging.info("processing irrep %d/%d" % (iri, ss.nirreps))
|
||||
LU = None # to trigger garbage collection before the next call
|
||||
translation_matrix = None
|
||||
LU = ssw.scatter_solver(iri)
|
||||
logging.info("LU solver created")
|
||||
#translation_matrix = ss.translation_matrix_packed(wavenumber, iri, BesselType.REGULAR) + np.eye(ss.saecv_sizes[iri])
|
||||
#logging.info("auxillary translation matrix created")
|
||||
|
||||
scattered_ir[iri] = np.zeros((nsp, nelem, ss.saecv_sizes[iri]), dtype=complex)
|
||||
scattered_ir_unpacked = np.zeros((nsp, nelem, ss.fecv_size), dtype=complex)
|
||||
|
||||
for spi in range(nsp):
|
||||
for y in range(nelem):
|
||||
ã = driving_full_sliced[spi,y]
|
||||
ãi = cleanarray(ss.pack_vector(ã, iri), copy=False)
|
||||
if np.all(ãi == 0):
|
||||
ir_contained[spi, y, iri] = False
|
||||
continue
|
||||
Tã = ssw.apply_Tmatrices_full(ã)
|
||||
Tãi = ss.pack_vector(Tã, iri)
|
||||
fi = LU(Tãi)
|
||||
scattered_ir[iri][spi, y] = fi
|
||||
scattered_ir_unpacked[spi, y] = ss.unpack_vector(fi, iri)
|
||||
scattered_full[spi, y] += scattered_ir_unpacked[spi, y]
|
||||
if a.save_gradually:
|
||||
iriout = outfile_tmp + ".%d" % iri
|
||||
np.savez(iriout, iri=iri, meta={**vars(a), 'qpms_version' : qpms.__version__()},
|
||||
omega=omega, wavenumber=wavenumber, nelem=nelem, wavevector=np.array(a.wavevector), phases=phases,
|
||||
positions = ss.positions[:,:2],
|
||||
scattered_ir_packed = scattered_ir[iri],
|
||||
scattered_ir_full = scattered_ir_unpacked,
|
||||
)
|
||||
logging.info("partial results saved to %s"%iriout)
|
||||
|
||||
t, l, m = bspec.tlm()
|
||||
|
||||
if not math.isnan(a.ccd_distance):
|
||||
logging.info("Computing the far fields")
|
||||
if math.isnan(a.ccd_size):
|
||||
a.ccd_size = (50 * a.ccd_distance / (max(Nx*px, Ny*py) *ssw.wavenumber.real))
|
||||
ccd_size = a.ccd_size
|
||||
ccd_x = np.linspace(-ccd_size/2, ccd_size/2, a.ccd_resolution)
|
||||
ccd_y = np.linspace(-ccd_size/2, ccd_size/2, a.ccd_resolution)
|
||||
ccd_grid = np.meshgrid(ccd_x, ccd_y, (a.ccd_distance,), indexing='ij')
|
||||
ccd_points = np.swapaxes(np.stack(ccd_grid, axis=-1).squeeze(axis=-2), 0,1) # First axis is y, second is x, because of imshow...
|
||||
ccd_fields = np.empty((nsp, nelem,) + ccd_points.shape, dtype=complex)
|
||||
for spi in range(nsp):
|
||||
for y in range(nelem):
|
||||
ccd_fields[spi, y] = ssw.scattered_E(scattered_full[spi, y], ccd_points, btyp=BesselType.HANKEL_PLUS)
|
||||
logging.info("Far fields done")
|
||||
|
||||
outfile = defaultprefix + ".npz" if a.output is None else a.output
|
||||
np.savez(outfile, meta={**vars(a), 'qpms_version' : qpms.__version__()},
|
||||
omega=omega, wavenumber=wavenumber, nelem=nelem, wavevector=np.array(a.wavevector), phases=phases,
|
||||
positions = ss.positions[:,:2],
|
||||
scattered_ir_packed = np.array(scattered_ir, dtype=np.object),
|
||||
scattered_full = scattered_full,
|
||||
ir_contained = ir_contained,
|
||||
t=t, l=l, m=m,
|
||||
iris1 = iris1 if (a.symmetry_adapted is not None) else None,
|
||||
irnames1 = ss1.irrep_names if (a.symmetry_adapted is not None) else None,
|
||||
fvcs1 = fvcs1 if (a.symmetry_adapted is not None) else None,
|
||||
#ccd_size = ccd_size if not math.isnan(a.ccd_distance) else None,
|
||||
ccd_points = ccd_points if not math.isnan(a.ccd_distance) else None,
|
||||
ccd_fields = ccd_fields if not math.isnan(a.ccd_distance) else None,
|
||||
)
|
||||
logging.info("Saved to %s" % outfile)
|
||||
|
||||
|
||||
if a.plot or (a.plot_out is not None):
|
||||
|
||||
|
||||
import matplotlib
|
||||
matplotlib.use('pdf')
|
||||
from matplotlib import pyplot as plt, cm
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
t, l, m = bspec.tlm()
|
||||
phasecm = cm.twilight
|
||||
pmcm = cm.bwr
|
||||
abscm = cm.plasma
|
||||
|
||||
plotfile = defaultprefix + ".pdf" if a.plot_out is None else a.plot_out
|
||||
pp = PdfPages(plotfile)
|
||||
|
||||
for spi in range(nsp):
|
||||
fig, axes = plt.subplots(nelem, 12 if math.isnan(a.ccd_distance) else 16, figsize=(figscale*(12 if math.isnan(a.ccd_distance) else 16), figscale*nelem))
|
||||
for yp in range(0,3): # TODO xy-dipoles instead?
|
||||
axes[0,4*yp+0].set_title("abs / (E,1,%s)" % realdipfieldlabels(yp))
|
||||
axes[0,4*yp+1].set_title("arg / (E,1,%s)" % realdipfieldlabels(yp))
|
||||
axes[0,4*yp+2].set_title("Fabs / (E,1,%s)" % realdipfieldlabels(yp))
|
||||
axes[0,4*yp+3].set_title("Farg / (E,1,%s)" % realdipfieldlabels(yp))
|
||||
if not math.isnan(a.ccd_distance):
|
||||
#axes[0,12].set_title("$E_{xy}$ @ $z = %g; \phi$" % a.ccd_distance)
|
||||
#axes[0,13].set_title("$E_{xy}$ @ $z = %g; \phi + \pi/2$" % a.ccd_distance)
|
||||
axes[0,12].set_title("$|E_{x}|^2$ @ $z = %g\,\mathrm{m}$" % a.ccd_distance)
|
||||
axes[0,13].set_title("$|E_{y}|^2$ @ $z = %g\,\mathrm{m}$" % a.ccd_distance)
|
||||
axes[0,14].set_title("$|E_x + E_y|^2$ @ $z = %g\,\mathrm{m}$" % a.ccd_distance)
|
||||
axes[0,15].set_title("$|E_{z}|^2$ @ $z = %g\,\mathrm{m}$" % a.ccd_distance)
|
||||
for gg in range(12,16):
|
||||
axes[-1,gg].set_xlabel("$x/\mathrm{m}$")
|
||||
|
||||
|
||||
for y in range(nelem):
|
||||
fulvec = scattered_full[spi,y]
|
||||
if a.symmetry_adapted is not None:
|
||||
driving_nonzero_y = [j for j in range(nelem) if abs(fvcs1[y,j]) > 1e-5]
|
||||
driving_descr = ss1.irrep_names[iris1[y]]+'\n'+', '.join(('$'+cplx_nicestr(fvcs1[y,j])+'$' +
|
||||
"(%s,%d,%+d)" % (("E" if t[j] == 2 else "M"), l[j], m[j]) for j in
|
||||
driving_nonzero_y)) # TODO shorten the complex number precision
|
||||
else:
|
||||
driving_descr = "%s,%d,%+d"%('E' if t[y]==2 else 'M', l[y], m[y],)
|
||||
axes[y,0].set_ylabel(driving_descr)
|
||||
axes[y,-1].yaxis.set_label_position("right")
|
||||
axes[y,-1].set_ylabel("$y/\mathrm{m}$\n"+driving_descr)
|
||||
vecgrid = fullvec2grid(fulvec, swapxy=True)
|
||||
vecgrid_ff = np.fft.fftshift(np.fft.fft2(vecgrid, axes=(0,1)),axes=(0,1))
|
||||
lemax = np.amax(abs(vecgrid))
|
||||
for yp in range(0,3):
|
||||
if(np.amax(abs(realdipfields(vecgrid,yp))) > lemax*1e-5):
|
||||
axes[y,yp*4].imshow(abs(realdipfields(vecgrid,yp)), vmin=0, interpolation='none')
|
||||
axes[y,yp*4].text(0.5, 0.5, '%g' % np.amax(abs(realdipfields(vecgrid,yp))), horizontalalignment='center', verticalalignment='center', transform=axes[y,yp*4].transAxes)
|
||||
axes[y,yp*4+1].imshow(np.angle(realdipfields(vecgrid,yp)), vmin=-np.pi, vmax=np.pi, cmap=phasecm, interpolation='none')
|
||||
axes[y,yp*4+2].imshow(abs(realdipfields(vecgrid_ff,yp)), vmin=0, interpolation='none')
|
||||
axes[y,yp*4+3].imshow(np.angle(realdipfields(vecgrid_ff,yp)), vmin=-np.pi, vmax=np.pi, cmap=phasecm, interpolation='none')
|
||||
else:
|
||||
for c in range(0,4):
|
||||
axes[y,yp*4+c].tick_params(bottom=False, left=False, labelbottom=False, labelleft=False)
|
||||
if not math.isnan(a.ccd_distance):
|
||||
fxye=(-ccd_size/2, ccd_size/2, -ccd_size/2, ccd_size/2)
|
||||
e2vmax = np.amax(np.linalg.norm(ccd_fields[spi,y], axis=-1)**2)
|
||||
xint = abs(ccd_fields[spi,y,...,0])**2
|
||||
yint = abs(ccd_fields[spi,y,...,1])**2
|
||||
xyint = abs(ccd_fields[spi,y,...,0] + ccd_fields[spi,y,...,1])**2
|
||||
zint = abs(ccd_fields[spi,y,...,2])**2
|
||||
xintmax = np.amax(xint)
|
||||
yintmax = np.amax(yint)
|
||||
zintmax = np.amax(zint)
|
||||
xyintmax = np.amax(xyint)
|
||||
axes[y, 12].imshow(xint, origin="lower", extent=fxye, cmap=abscm, interpolation='none')
|
||||
axes[y, 13].imshow(yint, origin="lower", extent=fxye, cmap=abscm, interpolation='none')
|
||||
axes[y, 14].imshow(xyint, origin="lower", extent=fxye, cmap=abscm, interpolation='none')
|
||||
axes[y, 15].imshow(zint, origin='lower', extent=fxye, cmap=abscm, interpolation='none')
|
||||
axes[y, 12].text(0.5, 0.5, '%g\n%g' % (xintmax,xintmax/e2vmax),
|
||||
horizontalalignment='center', verticalalignment='center', transform=axes[y,12].transAxes)
|
||||
axes[y, 13].text(0.5, 0.5, '%g\n%g' % (yintmax,yintmax/e2vmax),
|
||||
horizontalalignment='center', verticalalignment='center', transform=axes[y,13].transAxes)
|
||||
axes[y, 14].text(0.5, 0.5, '%g\n%g' % (xyintmax,xyintmax/e2vmax),
|
||||
horizontalalignment='center', verticalalignment='center', transform=axes[y,14].transAxes)
|
||||
axes[y, 15].text(0.5, 0.5, '%g\n%g' % (zintmax,zintmax/e2vmax),
|
||||
horizontalalignment='center', verticalalignment='center', transform=axes[y,15].transAxes)
|
||||
for gg in range(12,16):
|
||||
axes[y,gg].yaxis.tick_right()
|
||||
for gg in range(12,15):
|
||||
axes[y,gg].yaxis.set_major_formatter(plt.NullFormatter())
|
||||
fig.text(0, 0, str(slicepairs[spi]), horizontalalignment='left', verticalalignment='bottom')
|
||||
pp.savefig()
|
||||
annotate_pdf_metadata(pp, scriptname="finiterectlat-constant-driving.py")
|
||||
pp.close()
|
||||
|
||||
exit(0)
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import math
|
||||
from qpms.argproc import ArgParser
|
||||
from qpms.argproc import ArgParser, annotate_pdf_metadata
|
||||
|
||||
|
||||
ap = ArgParser(['rectlattice2d_finite', 'single_particle', 'single_lMax', ])
|
||||
ap = ArgParser(['rectlattice2d_finite', 'background_analytical', 'single_particle', 'single_lMax', ])
|
||||
|
||||
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')
|
||||
|
@ -19,8 +19,9 @@ ap.add_argument("-f", "--centre", type=complex, required=True, help='Contour cen
|
|||
ap.add_argument("--ai", type=float, default=0.05, help="Contour imaginary half-axis in eV")
|
||||
ap.add_argument("--ar", type=float, default=0.05, help="Contour real half-axis in eV")
|
||||
ap.add_argument("-N", type=int, default="150", help="Integration contour discretisation size")
|
||||
ap.add_argument("--D2", action='store_true', help="Use D2h symmetry even if the array has square symmetry")
|
||||
|
||||
ap.add_argument("--irrep", type=str, default="none", help="Irrep subspace (irrep index from 0 to 7, irrep label, or 'none' for no irrep decomposition")
|
||||
ap.add_argument("--irrep", type=str, default="none", help="Irrep subspace (irrep index from 0 to 7 (9 for D4h), irrep label, or 'none' for no irrep decomposition")
|
||||
|
||||
a=ap.parse_args()
|
||||
|
||||
|
@ -30,11 +31,15 @@ logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
|
|||
Nx, Ny = a.size
|
||||
px, py = a.period
|
||||
|
||||
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_n%g_L%d_c(%s±%g±%gj)eV_cn%d" % (
|
||||
particlestr, px*1e9, py*1e9, Nx, Ny, str(a.material), a.refractive_index, a.lMax,
|
||||
str(a.centre), a.ai, a.ar, a.N)
|
||||
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,
|
||||
str(a.centre), a.ar, a.ai, a.N,
|
||||
thegroup,
|
||||
)
|
||||
logging.info("Default file prefix: %s" % defaultprefix)
|
||||
|
||||
def inside_ellipse(point_xy, centre_xy, halfaxes_xy):
|
||||
|
@ -69,9 +74,9 @@ bspec = BaseSpec(lMax = a.lMax)
|
|||
medium = EpsMuGenerator(ap.background_epsmu)
|
||||
particles= [Particle(orig_xy[i], ap.tmgen, bspec) for i in np.ndindex(orig_xy.shape[:-1])]
|
||||
|
||||
sym = FinitePointGroup(point_group_info['D2h'])
|
||||
sym = FinitePointGroup(point_group_info[thegroup])
|
||||
logging.info("Creating scattering system object")
|
||||
ss, ssw = ScatteringSystem.create(particles, medium, sym, a.centre * eh)
|
||||
ss, ssw = ScatteringSystem.create(particles, medium, a.centre * eh, sym=sym)
|
||||
|
||||
if a.irrep == 'none':
|
||||
iri = None # no irrep decomposition
|
||||
|
@ -95,7 +100,7 @@ results['inside_contour'] = inside_ellipse((results['eigval'].real, results['eig
|
|||
results['refractive_index_internal'] = [medium(om).n for om in results['eigval']]
|
||||
|
||||
outfile = defaultprefix + (('_ir%s_%s.npz' % (str(iri), irname)) if iri is not None else '.npz') if a.output is None else a.output
|
||||
np.savez(outfile, meta=vars(a), **results)
|
||||
np.savez(outfile, meta={**vars(a), 'qpms_version' : qpms.__version__()}, **results)
|
||||
logging.info("Saved to %s" % outfile)
|
||||
|
||||
exit(0)
|
||||
|
@ -105,7 +110,7 @@ if a.plot or (a.plot_out is not None):
|
|||
import matplotlib
|
||||
matplotlib.use('pdf')
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(111)
|
||||
ax.plot(sinalpha_list, σ_ext*1e12,label='$\sigma_\mathrm{ext}$')
|
||||
|
@ -114,9 +119,11 @@ if a.plot or (a.plot_out is not None):
|
|||
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)
|
||||
with PdfPages(plotfile) as pdf:
|
||||
pdf.savefig(fig)
|
||||
annotate_pdf_metadata(pdf, scriptname='finiterectlat-modes.py')
|
||||
|
||||
exit(0)
|
||||
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from qpms.argproc import ArgParser, annotate_pdf_metadata
|
||||
import math
|
||||
from qpms.argproc import ArgParser
|
||||
pi = math.pi
|
||||
|
||||
|
||||
ap = ArgParser(['rectlattice2d_finite', 'single_particle', 'single_lMax', 'single_omega'])
|
||||
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 = ArgParser(['rectlattice2d_finite', 'single_particle', 'single_lMax', '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("-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")
|
||||
ap.add_argument("-g", "--save-gradually", action='store_true', help="saves the partial result after computing each irrep")
|
||||
|
@ -19,18 +17,9 @@ a=ap.parse_args()
|
|||
import logging
|
||||
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
|
||||
|
||||
Nx, Ny = a.size
|
||||
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_n%g_angles(%g_%g)_Ey_f%geV_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)
|
||||
|
||||
|
||||
import numpy as np
|
||||
import qpms
|
||||
from qpms.qpms_p import cart2sph, sph2cart, sph_loccart2cart, sph_loccart_basis
|
||||
from qpms.cybspec import BaseSpec
|
||||
from qpms.cytmatrices import CTMatrix, TMatrixGenerator
|
||||
from qpms.qpms_c import Particle
|
||||
|
@ -42,94 +31,209 @@ eh = eV/hbar
|
|||
|
||||
dbgmsg_enable(DebugFlags.INTEGRATION)
|
||||
|
||||
Nx, Ny = a.size
|
||||
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, )
|
||||
logging.info("Default file prefix: %s" % defaultprefix)
|
||||
|
||||
|
||||
#Particle positions
|
||||
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
|
||||
|
||||
orig_xy = np.stack(np.meshgrid(orig_x, orig_y), axis = -1)
|
||||
|
||||
|
||||
omega = ap.omega
|
||||
|
||||
bspec = BaseSpec(lMax = a.lMax)
|
||||
Tmatrix = ap.tmgen(bspec, ap.omega)
|
||||
particles= [Particle(orig_xy[i], Tmatrix) 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'])
|
||||
ss = ScatteringSystem(particles, sym)
|
||||
ss, ssw = ScatteringSystem.create(particles, ap.background_emg, ap.allomegas[0], sym=sym)
|
||||
|
||||
wavenumber = ap.background_epsmu.k(omega).real # Currently, ScatteringSystem does not "remember" frequency nor wavenumber
|
||||
|
||||
sinalpha_list = np.linspace(a.kx_lim[0],a.kx_lim[1],a.N)
|
||||
## Plane wave data
|
||||
a.theta = np.atleast_1d(np.array(a.theta))
|
||||
dir_sph_list = np.stack((np.broadcast_to(1, a.theta.shape), a.theta, np.broadcast_to(a.phi, a.theta.shape)), axis=-1)
|
||||
sψ, cψ = math.sin(a.psi), math.cos(a.psi)
|
||||
sχ, cχ = math.sin(a.chi), math.cos(a.chi)
|
||||
E_sph = (0., cψ*cχ + 1j*sψ*sχ, sψ*cχ + 1j*cψ*sχ)
|
||||
|
||||
# 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
|
||||
dir_cart_list = sph2cart(dir_sph_list)
|
||||
E_cart_list = sph_loccart2cart(E_sph, dir_sph_list)
|
||||
|
||||
σ_ext_list_ir = np.empty((a.N, ss.nirreps), dtype=float)
|
||||
σ_scat_list_ir = np.empty((a.N, ss.nirreps), dtype=float)
|
||||
nfreq = len(ap.allomegas)
|
||||
ndir = a.theta.shape[0]
|
||||
|
||||
k_cart_arr = np.empty((nfreq, ndir, 3), dtype=float)
|
||||
wavenumbers = np.empty((nfreq,), dtype=float)
|
||||
|
||||
σ_ext_arr_ir = np.empty((nfreq, ndir, ss.nirreps), dtype=float)
|
||||
σ_scat_arr_ir = np.empty((nfreq, ndir, ss.nirreps), dtype=float)
|
||||
|
||||
outfile_tmp = defaultprefix + ".tmp" if a.output is None else a.output + ".tmp"
|
||||
|
||||
for iri in range(ss.nirreps):
|
||||
logging.info("processing irrep %d/%d" % (iri, ss.nirreps))
|
||||
LU = None # to trigger garbage collection before the next call
|
||||
translation_matrix = None
|
||||
LU = ss.scatter_solver(wavenumber,iri)
|
||||
logging.info("LU solver created")
|
||||
translation_matrix = ss.translation_matrix_packed(wavenumber, iri, BesselType.REGULAR) + np.eye(ss.saecv_sizes[iri])
|
||||
logging.info("auxillary translation matrix created")
|
||||
for i, omega in enumerate(ap.allomegas):
|
||||
logging.info("Processing frequency %g eV" % (omega / eV,))
|
||||
if i != 0:
|
||||
ssw = ss(omega)
|
||||
if ssw.wavenumber.imag != 0:
|
||||
warnings.warn("The background medium wavenumber has non-zero imaginary part. Don't expect emaningful results for cross sections.")
|
||||
wavenumber = ssw.wavenumber.real
|
||||
wavenumbers[i] = wavenumber
|
||||
|
||||
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(ã)
|
||||
k_sph_list = np.array(dir_sph_list, copy=True)
|
||||
k_sph_list[:,0] = wavenumber
|
||||
|
||||
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
|
||||
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)
|
||||
k_cart_arr[i] = sph2cart(k_sph_list)
|
||||
|
||||
σ_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)
|
||||
for iri in range(ss.nirreps):
|
||||
logging.info("processing irrep %d/%d" % (iri, ss.nirreps))
|
||||
LU = None # to trigger garbage collection before the next call
|
||||
translation_matrix = None
|
||||
LU = ssw.scatter_solver(iri)
|
||||
logging.info("LU solver created")
|
||||
translation_matrix = ssw.translation_matrix_packed(iri, BesselType.REGULAR) + np.eye(ss.saecv_sizes[iri])
|
||||
logging.info("auxillary translation matrix created")
|
||||
|
||||
for j in range(ndir):
|
||||
k_cart = k_cart_arr[i,j]
|
||||
# the following two could be calculated only once, but probably not a big deal
|
||||
ã = ss.planewave_full(k_cart=k_cart_arr[i,j], E_cart=E_cart_list[j])
|
||||
Tã = ssw.apply_Tmatrices_full(ã)
|
||||
|
||||
Tãi = ss.pack_vector(Tã, iri)
|
||||
ãi = ss.pack_vector(ã, iri)
|
||||
fi = LU(Tãi)
|
||||
σ_ext_arr_ir[i, j, iri] = -np.vdot(ãi, fi).real/wavenumber**2
|
||||
σ_scat_arr_ir[i, j, iri] = np.vdot(fi,np.dot(translation_matrix, fi)).real/wavenumber**2
|
||||
if a.save_gradually:
|
||||
iriout = outfile_tmp + ".%d.%d" % (i, iri)
|
||||
np.savez(iriout, omegai=i, iri=iri, meta={**vars(a), 'qpms_version' : qpms.__version__()}, omega=omega, k_sph=k_sph_list, k_cart = k_cart_arr, E_cart=E_cart_list, E_sph=np.array(E_sph),
|
||||
wavenumber=wavenumber, σ_ext_list_ir=σ_ext_arr_ir[i,:,iri], σ_scat_list_ir=σ_scat_list_ir[i,:,iri])
|
||||
logging.info("partial results saved to %s"%iriout)
|
||||
|
||||
σ_abs_arr_ir = σ_ext_arr_ir - σ_scat_arr_ir
|
||||
σ_abs_arr = np.sum(σ_abs_arr_ir, axis=-1)
|
||||
σ_scat_arr = np.sum(σ_scat_arr_ir, axis=-1)
|
||||
σ_ext_arr = np.sum(σ_ext_arr_ir, axis=-1)
|
||||
|
||||
|
||||
outfile = defaultprefix + ".npz" if a.output is None else a.output
|
||||
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,
|
||||
σ_ext_ir=σ_ext_list_ir,σ_abs_ir=σ_abs_list_ir,σ_scat_ir=σ_scat_list_ir, omega=omega, wavenumber=wavenumber
|
||||
np.savez(outfile, meta={**vars(a), 'qpms_version' : qpms.__version__()},
|
||||
k_sph=k_sph_list, k_cart = k_cart_arr, E_cart=E_cart_list, E_sph=np.array(E_sph),
|
||||
σ_ext=σ_ext_arr,σ_abs=σ_abs_arr,σ_scat=σ_scat_arr,
|
||||
σ_ext_ir=σ_ext_arr_ir,σ_abs_ir=σ_abs_arr_ir,σ_scat_ir=σ_scat_arr_ir, omega=ap.allomegas, wavenumbers=wavenumbers
|
||||
)
|
||||
logging.info("Saved to %s" % outfile)
|
||||
|
||||
|
||||
if a.plot or (a.plot_out is not None):
|
||||
import matplotlib
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
matplotlib.use('pdf')
|
||||
from matplotlib import pyplot as plt
|
||||
from scipy.interpolate import griddata
|
||||
|
||||
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)
|
||||
with PdfPages(plotfile) as pdf:
|
||||
ipm = 'nearest'
|
||||
sintheta = np.sin(a.theta)
|
||||
if False: #len(ap.omega_ranges) != 0:
|
||||
# angle plot ---------------------------------
|
||||
fig = plt.figure(figsize=(210/25.4, 297/25.4))
|
||||
vmax = max(np.amax(σ_ext_arr), np.amax(σ_scat_arr), np.amax(σ_abs_arr))
|
||||
vmin = min(np.amin(σ_ext_arr), np.amin(σ_scat_arr), np.amin(σ_abs_arr))
|
||||
|
||||
ax = fig.add_subplot(311)
|
||||
ax.pcolormesh(a.theta, ap.allomegas/eh, σ_ext_arr, vmin=vmin, vmax=vmax)
|
||||
ax.set_xlabel('$\\theta$')
|
||||
ax.set_ylabel('$\\hbar\\omega / \\mathrm{eV}$')
|
||||
ax.set_title('$\\sigma_\\mathrm{ext}$')
|
||||
|
||||
ax = fig.add_subplot(312)
|
||||
ax.pcolormesh(a.theta, ap.allomegas/eh, σ_scat_arr, vmin=vmin, vmax=vmax)
|
||||
ax.set_xlabel('$\\theta$')
|
||||
ax.set_ylabel('$\\hbar\\omega / \\mathrm{eV}$')
|
||||
ax.set_title('$\\sigma_\\mathrm{scat}$')
|
||||
|
||||
ax = fig.add_subplot(313)
|
||||
im = ax.pcolormesh(a.theta, ap.allomegas/eh, σ_abs_arr, vmin=vmin, vmax=vmax)
|
||||
ax.set_xlabel('$\\theta$')
|
||||
ax.set_ylabel('$\\hbar\\omega / \\mathrm{eV}$')
|
||||
ax.set_title('$\\sigma_\\mathrm{abs}$')
|
||||
|
||||
|
||||
fig.subplots_adjust(right=0.8)
|
||||
fig.colorbar(im, cax = fig.add_axes([0.85, 0.15, 0.05, 0.7]))
|
||||
|
||||
pdf.savefig(fig)
|
||||
plt.close(fig)
|
||||
|
||||
if len(ap.omega_ranges) != 0:
|
||||
# "k-space" plot -----------------------------
|
||||
domega = np.amin(np.diff(ap.allomegas))
|
||||
dsintheta = np.amin(abs(np.diff(sintheta)))
|
||||
dk = dsintheta * wavenumbers[0]
|
||||
|
||||
# target image grid
|
||||
grid_y, grid_x = np.mgrid[ap.allomegas[0] : ap.allomegas[-1] : domega, np.amin(sintheta) * wavenumbers[-1] : np.amax(sintheta) * wavenumbers[-1] : dk]
|
||||
imextent = (np.amin(sintheta) * wavenumbers[-1] / 1e6, np.amax(sintheta) * wavenumbers[-1] / 1e6, ap.allomegas[0] / eh, ap.allomegas[-1] / eh)
|
||||
|
||||
# source coordinates for griddata
|
||||
ktheta = sintheta[None, :] * wavenumbers[:, None]
|
||||
omegapoints = np.broadcast_to(ap.allomegas[:, None], ktheta.shape)
|
||||
points = np.stack( (ktheta.flatten(), omegapoints.flatten()), axis = -1)
|
||||
|
||||
fig = plt.figure(figsize=(210/25.4, 297/25.4))
|
||||
vmax = np.amax(σ_ext_arr)
|
||||
|
||||
ax = fig.add_subplot(311)
|
||||
grid_z = griddata(points, σ_ext_arr.flatten(), (grid_x, grid_y), method = ipm)
|
||||
ax.imshow(grid_z, extent = imextent, origin = 'lower', vmin = 0, vmax = vmax, aspect = 'auto', interpolation='none')
|
||||
ax.set_xlabel('$k_\\theta / \\mathrm{\\mu m^{-1}}$')
|
||||
ax.set_ylabel('$\\hbar\\omega / \\mathrm{eV}$')
|
||||
ax.set_title('$\\sigma_\\mathrm{ext}$')
|
||||
|
||||
ax = fig.add_subplot(312)
|
||||
grid_z = griddata(points, σ_scat_arr.flatten(), (grid_x, grid_y), method = ipm)
|
||||
ax.imshow(grid_z, extent = imextent, origin = 'lower', vmin = 0, vmax = vmax, aspect = 'auto', interpolation='none')
|
||||
ax.set_xlabel('$k_\\theta / \\mathrm{\\mu m^{-1}}$')
|
||||
ax.set_ylabel('$\\hbar\\omega / \\mathrm{eV}$')
|
||||
ax.set_title('$\\sigma_\\mathrm{scat}$')
|
||||
|
||||
ax = fig.add_subplot(313)
|
||||
grid_z = griddata(points, σ_abs_arr.flatten(), (grid_x, grid_y), method = ipm)
|
||||
im = ax.imshow(grid_z, extent = imextent, origin = 'lower', vmin = 0, vmax = vmax, aspect = 'auto', interpolation='none')
|
||||
ax.set_xlabel('$k_\\theta / \\mathrm{\\mu m^{-1}}$')
|
||||
ax.set_ylabel('$\\hbar\\omega / \\mathrm{eV}$')
|
||||
ax.set_title('$\\sigma_\\mathrm{abs}$')
|
||||
|
||||
fig.subplots_adjust(right=0.8)
|
||||
fig.colorbar(im, cax = fig.add_axes([0.85, 0.15, 0.05, 0.7]))
|
||||
|
||||
pdf.savefig(fig)
|
||||
plt.close(fig)
|
||||
|
||||
for omega in ap.omega_singles:
|
||||
i = np.searchsorted(ap.allomegas, omega)
|
||||
|
||||
fig = plt.figure()
|
||||
fig.suptitle("%g eV" % (omega / eh))
|
||||
ax = fig.add_subplot(111)
|
||||
sintheta = np.sin(a.theta)
|
||||
ax.plot(sintheta, σ_ext_arr[i]*1e12,label='$\sigma_\mathrm{ext}$')
|
||||
ax.plot(sintheta, σ_scat_arr[i]*1e12, label='$\sigma_\mathrm{scat}$')
|
||||
ax.plot(sintheta, σ_abs_arr[i]*1e12, label='$\sigma_\mathrm{abs}$')
|
||||
ax.legend()
|
||||
ax.set_xlabel('$\sin\\theta$')
|
||||
ax.set_ylabel('$\sigma/\mathrm{\mu m^2}$')
|
||||
|
||||
pdf.savefig(fig)
|
||||
plt.close(fig)
|
||||
annotate_pdf_metadata(pdf, scriptname="finiterectlat-scatter.py")
|
||||
|
||||
|
||||
exit(0)
|
||||
|
||||
|
|
|
@ -1,376 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse, re, random, string, sys
|
||||
import subprocess
|
||||
import warnings
|
||||
from scipy.constants import hbar, e as eV, pi, c
|
||||
|
||||
unitcell_size = 1 # rectangular lattice
|
||||
unitcell_indices = tuple(range(unitcell_size))
|
||||
|
||||
def make_action_sharedlist(opname, listname):
|
||||
class opAction(argparse.Action):
|
||||
def __call__(self, parser, args, values, option_string=None):
|
||||
if (not hasattr(args, listname)) or getattr(args, listname) is None:
|
||||
setattr(args, listname, list())
|
||||
getattr(args,listname).append((opname, values))
|
||||
return opAction
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
#TODO? použít type=argparse.FileType('r') ?
|
||||
parser.add_argument('--TMatrix', action='store', required=True, help='Path to TMatrix file')
|
||||
#parser.add_argument('--griddir', action='store', required=True, help='Path to the directory with precalculated translation operators')
|
||||
parser.add_argument('--output_prefix', '-p', '-o', action='store', required=True, help='Prefix to the npz output (will be appended frequency, hexside and chunkno)')
|
||||
parser.add_argument('--nosuffix', action='store_true', help='Do not add dimension metadata to the output filenames')
|
||||
#sizepar = parser.add_mutually_exclusive_group(required=True)
|
||||
#parser.add_argument('--hexside', action='store', type=float, required=True, help='Lattice hexagon size length')
|
||||
parser.add_argument('--dx', action='store', type=float, required=True, help='x-direction lattice constant')
|
||||
parser.add_argument('--dy', action='store', type=float, required=True, help='y-direction lattice constant')
|
||||
|
||||
parser.add_argument('--Nx', '--nx', action='store', type=int, required=True, help='Lattice points in the x-direction')
|
||||
parser.add_argument('--Ny', '--ny', action='store', type=int, required=True, help='Lattice points in the y-direction')
|
||||
|
||||
# In these default settings, the area is 2x2 times larger than first BZ
|
||||
parser.add_argument('--kxmin', action='store', type=float, default=-1., help='TODO')
|
||||
parser.add_argument('--kxmax', action='store', type=float, default=1., help='TODO')
|
||||
parser.add_argument('--kymin', action='store', type=float, default=-1., help='TODO')
|
||||
parser.add_argument('--kymax', action='store', type=float, default=1., help='TODO')
|
||||
|
||||
#parser.add_argument('--kdensity', action='store', type=int, default=33, help='Number of k-points per x-axis segment')
|
||||
parser.add_argument('--kxdensity', action='store', type=int, default=51, help='k-space resolution in the x-direction')
|
||||
parser.add_argument('--kydensity', action='store', type=int, default=51, help='k-space resolution in the y-direction')
|
||||
|
||||
partgrp = parser.add_mutually_exclusive_group()
|
||||
partgrp.add_argument('--only_TE', action='store_true', help='Calculate only the projection on the E⟂z modes')
|
||||
partgrp.add_argument('--only_TM', action='store_true', help='Calculate only the projection on the E∥z modes')
|
||||
partgrp.add_argument('--serial', action='store_true', help='Calculate the TE and TM parts separately to save memory')
|
||||
|
||||
parser.add_argument('--nocentre', action='store_true', help='Place the coordinate origin to the left bottom corner rather that to the centre of the array')
|
||||
|
||||
parser.add_argument('--plot_TMatrix', action='store_true', help='Visualise TMatrix on the first page of the output')
|
||||
#parser.add_argument('--SVD_output', action='store', help='Path to output singular value decomposition result')
|
||||
parser.add_argument('--maxlayer', action='store', type=int, default=100, help='How far to sum the lattice points to obtain the dispersion')
|
||||
parser.add_argument('--scp_to', action='store', metavar='N', type=str, help='SCP the output files to a given destination')
|
||||
parser.add_argument('--background_permittivity', action='store', type=float, default=1., help='Background medium relative permittivity (default 1)')
|
||||
parser.add_argument('--eVfreq', action='store', required=True, type=float, help='Frequency in eV')
|
||||
|
||||
parser.add_argument('--chunklen', action='store', type=int, default=3000, help='Number of k-points per output file (default 3000)')
|
||||
parser.add_argument('--lMax', action='store', type=int, help='Override lMax from the TMatrix file')
|
||||
#TODO some more sophisticated x axis definitions
|
||||
#parser.add_argument('--gaussian', action='store', type=float, metavar='σ', help='Use a gaussian envelope for weighting the interaction matrix contributions (depending on the distance), measured in unit cell lengths (?) FIxME).')
|
||||
parser.add_argument('--verbose', '-v', action='count', help='Be verbose (about computation times, mostly)')
|
||||
popgrp=parser.add_argument_group(title='Operations')
|
||||
popgrp.add_argument('--tr', dest='ops', action=make_action_sharedlist('tr', 'ops'), default=list()) # the default value for dest can be set once
|
||||
for i in unitcell_indices:
|
||||
popgrp.add_argument('--tr%d'%i, dest='ops', action=make_action_sharedlist('tr%d'%i, 'ops'))
|
||||
popgrp.add_argument('--sym', dest='ops', action=make_action_sharedlist('sym', 'ops'))
|
||||
for i in unitcell_indices:
|
||||
popgrp.add_argument('--sym%d'%i, dest='ops', action=make_action_sharedlist('sym%d'%i, 'ops'))
|
||||
#popgrp.add_argument('--mult', dest='ops', nargs=3, metavar=('INCSPEC', 'SCATSPEC', 'MULTIPLIER'), action=make_action_sharedlist('mult', 'ops'))
|
||||
#popgrp.add_argument('--mult0', dest='ops', nargs=3, metavar=('INCSPEC', 'SCATSPEC', 'MULTIPLIER'), action=make_action_sharedlist('mult0', 'ops'))
|
||||
#popgrp.add_argument('--mult1', dest='ops', nargs=3, metavar=('INCSPEC', 'SCATSPEC', 'MULTIPLIER'), action=make_action_sharedlist('mult1', 'ops'))
|
||||
popgrp.add_argument('--multl', dest='ops', nargs=3, metavar=('INCL[,INCL,...]', 'SCATL[,SCATL,...]', 'MULTIPLIER'), action=make_action_sharedlist('multl', 'ops'))
|
||||
for i in unitcell_indices:
|
||||
popgrp.add_argument('--multl%d'%i, dest='ops', nargs=3, metavar=('INCL[,INCL,...]', 'SCATL[,SCATL,...]', 'MULTIPLIER'), action=make_action_sharedlist('multl%d'%i, 'ops'))
|
||||
#popgrp.add_argument('--multl1', dest='ops', nargs=3, metavar=('INCL[,INCL,...]', 'SCATL[,SCATL,...]', 'MULTIPLIER'), action=make_action_sharedlist('multl1', 'ops'))
|
||||
parser.add_argument('--frequency_multiplier', action='store', type=float, default=1., help='Multiplies the frequencies in the TMatrix file by a given factor.')
|
||||
# TODO enable more flexible per-sublattice specification
|
||||
pargs=parser.parse_args()
|
||||
if pargs.verbose:
|
||||
print(pargs, file = sys.stderr)
|
||||
|
||||
maxlayer=pargs.maxlayer
|
||||
eVfreq = pargs.eVfreq
|
||||
freq = eVfreq*eV/hbar
|
||||
verbose=pargs.verbose
|
||||
dy = pargs.dy
|
||||
dx = pargs.dx
|
||||
Ny = pargs.Ny
|
||||
Nx = pargs.Nx
|
||||
|
||||
TMatrix_file = pargs.TMatrix
|
||||
|
||||
epsilon_b = pargs.background_permittivity #2.3104
|
||||
#gaussianSigma = pargs.gaussian if pargs.gaussian else None # hexside * 222 / 7
|
||||
interpfreqfactor = pargs.frequency_multiplier
|
||||
scp_dest = pargs.scp_to if pargs.scp_to else None
|
||||
kxdensity = pargs.kxdensity
|
||||
kydensity = pargs.kydensity
|
||||
chunklen = pargs.chunklen
|
||||
|
||||
ops = list()
|
||||
opre = re.compile('(tr|sym|copy|multl|mult)(\d*)')
|
||||
for oparg in pargs.ops:
|
||||
opm = opre.match(oparg[0])
|
||||
if opm:
|
||||
ops.append(((opm.group(2),) if opm.group(2) else unitcell_indices, opm.group(1), oparg[1]))
|
||||
else:
|
||||
raise # should not happen
|
||||
if(verbose):
|
||||
print(ops, file = sys.stderr)
|
||||
|
||||
|
||||
# -----------------finished basic CLI parsing (except for op arguments) ------------------
|
||||
from qpms.timetrack import _time_b, _time_e
|
||||
btime=_time_b(verbose)
|
||||
|
||||
import qpms
|
||||
import numpy as np
|
||||
import os, warnings, math
|
||||
from scipy import interpolate
|
||||
nx = None
|
||||
s3 = math.sqrt(3)
|
||||
|
||||
|
||||
# specifikace T-matice zde
|
||||
refind = math.sqrt(epsilon_b)
|
||||
cdn = c / refind
|
||||
k_0 = freq * refind / c # = freq / cdn
|
||||
TMatrices_orig, freqs_orig, freqs_weirdunits_orig, lMaxTM = qpms.loadScuffTMatrices(TMatrix_file)
|
||||
lMax = lMaxTM
|
||||
if pargs.lMax:
|
||||
lMax = pargs.lMax if pargs.lMax else lMaxTM
|
||||
my, ny = qpms.get_mn_y(lMax)
|
||||
nelem = len(my)
|
||||
if pargs.lMax: #force commandline specified lMax
|
||||
TMatrices_orig = TMatrices_orig[...,0:nelem,:,0:nelem]
|
||||
TMatrices = np.array(np.broadcast_to(TMatrices_orig[:,nx,:,:,:,:],(len(freqs_orig),unitcell_size,2,nelem,2,nelem)) )
|
||||
xfl = qpms.xflip_tyty(lMax)
|
||||
yfl = qpms.yflip_tyty(lMax)
|
||||
zfl = qpms.zflip_tyty(lMax)
|
||||
c2rot = qpms.apply_matrix_left(qpms.yflip_yy(3),qpms.xflip_yy(3),-1)
|
||||
|
||||
reCN = re.compile('(\d*)C(\d+)')
|
||||
#TODO C nekonečno
|
||||
|
||||
for op in ops:
|
||||
if op[0] == 'all':
|
||||
#targets = (0,1)
|
||||
targets = unitcell_indices
|
||||
elif isinstance(op[0],int):
|
||||
targets = (op[0],)
|
||||
else:
|
||||
targets = op[0]
|
||||
|
||||
if op[1] == 'sym':
|
||||
mCN = reCN.match(op[2]) # Fuck van Rossum for not having assignments inside expressions
|
||||
if op[2] == 'σ_z':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(zfl,qpms.apply_ndmatrix_left(zfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'σ_y':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(yfl,qpms.apply_ndmatrix_left(yfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'σ_x':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(xfl,qpms.apply_ndmatrix_left(xfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'C2': # special case of the latter
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_matrix_left(c2rot,qpms.apply_matrix_left(c2rot, TMatrices[:,t], -3),-1))/2
|
||||
elif mCN:
|
||||
rotN = int(mCN.group(2))
|
||||
TMatrix_contribs = np.empty((rotN,TMatrices.shape[0],2,nelem,2,nelem), dtype=np.complex_)
|
||||
for t in targets:
|
||||
for i in range(rotN):
|
||||
rotangle = 2*np.pi*i / rotN
|
||||
rot = qpms.WignerD_yy_fromvector(lMax,np.array([0,0,rotangle]))
|
||||
rotinv = qpms.WignerD_yy_fromvector(lMax,np.array([0,0,-rotangle]))
|
||||
TMatrix_contribs[i] = qpms.apply_matrix_left(rot,qpms.apply_matrix_left(rotinv, TMatrices[:,t], -3),-1)
|
||||
TMatrices[:,t] = np.sum(TMatrix_contribs, axis=0) / rotN
|
||||
else:
|
||||
raise
|
||||
elif op[1] == 'tr':
|
||||
mCN = reCN.match(op[2]) # Fuck van Rossum for not having assignments inside expressions
|
||||
if op[2] == 'σ_z':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(zfl,qpms.apply_ndmatrix_left(zfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'σ_y':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(yfl,qpms.apply_ndmatrix_left(yfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'σ_x':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(xfl,qpms.apply_ndmatrix_left(xfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'C2':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_matrix_left(c2rot,qpms.apply_matrix_left(c2rot, TMatrices[:,t], -3),-1)
|
||||
elif mCN:
|
||||
rotN = int(mCN.group(2))
|
||||
power = int(mCN.group(1)) if mCN.group(1) else 1
|
||||
TMatrix_contribs = np.empty((rotN,TMatrices.shape[0],2,nelem,2,nelem), dtype=np.complex_)
|
||||
for t in targets:
|
||||
rotangle = 2*np.pi*power/rotN
|
||||
rot = qpms.WignerD_yy_fromvector(lMax, np.array([0,0,rotangle]))
|
||||
rotinv = qpms.WignerD_yy_fromvector(lMax, np.array([0,0,-rotangle]))
|
||||
TMatrices[:,t] = qpms.apply_matrix_left(rot, qpms.apply_matrix_left(rotinv, TMatrices[:,t], -3),-1)
|
||||
else:
|
||||
raise
|
||||
elif op[1] == 'copy':
|
||||
raise # not implemented
|
||||
elif op[1] == 'mult':
|
||||
raise # not implemented
|
||||
elif op[1] == 'multl':
|
||||
incy = np.full((nelem,), False, dtype=bool)
|
||||
for incl in op[2][0].split(','):
|
||||
l = int(incl)
|
||||
incy += (l == ny)
|
||||
scaty = np.full((nelem,), False, dtype=bool)
|
||||
for scatl in op[2][1].split(','):
|
||||
l = int(scatl)
|
||||
scaty += (l == ny)
|
||||
for t in targets:
|
||||
TMatrices[np.ix_(np.arange(TMatrices.shape[0]),np.array([t]),np.array([0,1]),scaty,np.array([0,1]),incy)] *= float(op[2][2])
|
||||
else:
|
||||
raise #unknown operation; should not happen
|
||||
|
||||
TMatrices_interp = interpolate.interp1d(freqs_orig*interpfreqfactor, TMatrices, axis=0, kind='linear',fill_value="extrapolate")
|
||||
|
||||
|
||||
xpositions = np.arange(Nx) * dx
|
||||
ypositions = np.arange(Ny) * dy
|
||||
if not pargs.nocentre:
|
||||
xpositions -= Nx * dx / 2
|
||||
ypositions -= Ny * dy / 2
|
||||
xpositions, ypositions = np.meshgrid(xpositions, ypositions, indexing='ij', copy=False)
|
||||
positions=np.stack((xpositions.ravel(),ypositions.ravel()), axis=-1)
|
||||
positions=positions[np.random.permutation(len(positions))]
|
||||
N = positions.shape[0]
|
||||
|
||||
kx = np.linspace(pargs.kxmin, pargs.kxmax, num=pargs.kxdensity, endpoint=True) * 2*np.pi / dx
|
||||
ky = np.linspace(pargs.kymin, pargs.kymax, num=pargs.kydensity, endpoint=True) * 2*np.pi / dy
|
||||
kx, ky = np.meshgrid(kx, ky, indexing='ij', copy=False)
|
||||
kz = np.sqrt(k_0**2 - (kx ** 2 + ky ** 2))
|
||||
|
||||
klist_full = np.stack((kx,ky,kz), axis=-1).reshape((-1,3))
|
||||
TMatrices_om = TMatrices_interp(freq)
|
||||
|
||||
chunkn = math.ceil(klist_full.size / 3 / chunklen)
|
||||
|
||||
if verbose:
|
||||
print('Evaluating %d k-points' % klist_full.size + ('in %d chunks'%chunkn) if chunkn>1 else '' , file = sys.stderr)
|
||||
sys.stderr.flush()
|
||||
|
||||
try:
|
||||
version = qpms.__version__
|
||||
except NameError:
|
||||
version = None
|
||||
|
||||
metadata = np.array({
|
||||
'script': os.path.basename(__file__),
|
||||
'version': version,
|
||||
'type' : 'Plane wave scattering on a finite rectangular lattice',
|
||||
'lMax' : lMax,
|
||||
'dx' : dx,
|
||||
'dy' : dy,
|
||||
'Nx' : Nx,
|
||||
'Ny' : Ny,
|
||||
#'maxlayer' : maxlayer,
|
||||
#'gaussianSigma' : gaussianSigma,
|
||||
'epsilon_b' : epsilon_b,
|
||||
#'hexside' : hexside,
|
||||
'chunkn' : chunkn,
|
||||
'chunki' : 0,
|
||||
'TMatrix_file' : TMatrix_file,
|
||||
'ops' : ops,
|
||||
'centred' : not pargs.nocentre
|
||||
})
|
||||
|
||||
|
||||
scat = qpms.Scattering_2D_zsym(positions, TMatrices_om, k_0, verbose=verbose)
|
||||
|
||||
if pargs.only_TE:
|
||||
actions = (0,)
|
||||
elif pargs.only_TM:
|
||||
actions = (1,)
|
||||
elif pargs.serial:
|
||||
actions = (0,1)
|
||||
else:
|
||||
actions = (None,)
|
||||
|
||||
xu = np.array((1,0,0))
|
||||
yu = np.array((0,1,0))
|
||||
zu = np.array((0,0,1))
|
||||
TEč, TMč = qpms.symz_indexarrays(lMax)
|
||||
|
||||
klist_full_2D = klist_full[...,:2]
|
||||
klist_full_dir = klist_full/np.linalg.norm(klist_full, axis=-1, keepdims=True)
|
||||
for action in actions:
|
||||
if action is None:
|
||||
scat.prepare(verbose=verbose)
|
||||
actionstring = ''
|
||||
else:
|
||||
scat.prepare_partial(action, verbose=verbose)
|
||||
actionstring = '.TM' if action else '.TE'
|
||||
for chunki in range(chunkn):
|
||||
sbtime = _time_b(verbose, step='Solving the scattering problem, chunk %d'%chunki+actionstring)
|
||||
if pargs.nosuffix:
|
||||
outfile = pargs.output_prefix + actionstring + (
|
||||
('.%03d' % chunki) if chunkn > 1 else '')
|
||||
else:
|
||||
outfile = '%s_%dx%d_%.0fnmx%.0fnm_%.4f%s%s.npz' % (
|
||||
pargs.output_prefix, Nx, Ny, dx/1e-9, dy/1e-9,
|
||||
eVfreq, actionstring,
|
||||
(".%03d" % chunki) if chunkn > 1 else '')
|
||||
|
||||
klist = klist_full[chunki * chunklen : (chunki + 1) * chunklen]
|
||||
klist2d = klist_full_2D[chunki * chunklen : (chunki + 1) * chunklen]
|
||||
klistdir = klist_full_dir[chunki * chunklen : (chunki + 1) * chunklen]
|
||||
|
||||
'''
|
||||
The following loop is a fuckup that has its roots in the fact that
|
||||
the function qpms.get_π̃τ̃_y1 in qpms_p.py is not vectorized
|
||||
(and consequently, neither is plane_pq_y.)
|
||||
|
||||
And Scattering_2D_zsym.scatter_partial is not vectorized, either.
|
||||
'''
|
||||
if action == 0 or action is None:
|
||||
xresult = np.full((klist.shape[0], N, nelem), np.nan, dtype=complex)
|
||||
yresult = np.full((klist.shape[0], N, nelem), np.nan, dtype=complex)
|
||||
if action == 1 or action is None:
|
||||
zresult = np.full((klist.shape[0], N, nelem), np.nan, dtype=complex)
|
||||
for i in range(klist.shape[0]):
|
||||
if math.isnan(klist[i,2]):
|
||||
if(verbose):
|
||||
print("%d. momentum %s invalid (k_0=%f), skipping" % (i, str(klist[i]),k_0))
|
||||
continue
|
||||
kdir = klistdir[i]
|
||||
phases = np.exp(-1j*np.sum(klist2d[i] * positions, axis=-1))
|
||||
if action == 0 or action is None:
|
||||
pq = np.array(qpms.plane_pq_y(lMax, kdir, xu)).ravel()[TEč] * phases[:, nx]
|
||||
xresult[i] = scat.scatter_partial(0, pq)
|
||||
pq = np.array(qpms.plane_pq_y(lMax, kdir, yu)).ravel()[TEč] * phases[:, nx]
|
||||
yresult[i] = scat.scatter_partial(0, pq)
|
||||
if action == 1 or action is None:
|
||||
pq = np.array(qpms.plane_pq_y(lMax, kdir, zu)).ravel()[TMč] * phases[:, nx]
|
||||
zresult[i] = scat.scatter_partial(1, pq)
|
||||
_time_e(sbtime, verbose, step='Solving the scattering problem, chunk %d'%chunki+actionstring)
|
||||
|
||||
metadata[()]['chunki'] = chunki
|
||||
if action is None:
|
||||
np.savez(outfile, omega = freq, klist = klist,
|
||||
metadata=metadata,
|
||||
positions=positions,
|
||||
ab_x=xresult,
|
||||
ab_y=yresult,
|
||||
ab_z=zresult
|
||||
)
|
||||
elif action == 0:
|
||||
np.savez(outfile, omega = freq, klist = klist,
|
||||
metadata=metadata,
|
||||
positions=positions,
|
||||
ab_x=xresult,
|
||||
ab_y=yresult,
|
||||
)
|
||||
elif action == 1:
|
||||
np.savez(outfile, omega = freq, klist = klist,
|
||||
metadata=metadata,
|
||||
positions=positions,
|
||||
ab_z=zresult
|
||||
)
|
||||
else:
|
||||
raise
|
||||
|
||||
if scp_dest:
|
||||
if outfile:
|
||||
subprocess.run(['scp', outfile, scp_dest])
|
||||
scat.forget_matrices() # free memory in case --serial was used
|
||||
|
||||
_time_e(btime, verbose)
|
|
@ -1,340 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
'''
|
||||
Bulk SVD mode computation for compact scatterer 2D lattices
|
||||
'''
|
||||
|
||||
__TODOs__ = '''
|
||||
BIG TODO: Use more efficient way to calculate the interaction sums: perhaps some customized Ewald-type summation?
|
||||
|
||||
Small TODOs:
|
||||
- Implement a more user-friendly way to define the lattice base vectors and positions of the particles.
|
||||
cf. https://stackoverflow.com/questions/2371436/evaluating-a-mathematical-expression-in-a-string/2371789
|
||||
- low priority: allow to perform some more custom operations on T-Matrix, using some kind of parsing from the previous point
|
||||
- Autodetect symmetries
|
||||
|
||||
'''
|
||||
import argparse, re, random, string
|
||||
import subprocess
|
||||
from scipy.constants import hbar, e as eV, pi, c
|
||||
import warnings
|
||||
|
||||
def make_action_sharedlist(opname, listname):
|
||||
class opAction(argparse.Action):
|
||||
def __call__(self, parser, args, values, option_string=None):
|
||||
if (not hasattr(args, listname)) or getattr(args, listname) is None:
|
||||
setattr(args, listname, list())
|
||||
getattr(args,listname).append((opname, values))
|
||||
return opAction
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
#TODO? použít type=argparse.FileType('r') ?
|
||||
#TODO create some user-friendlier way to define lattice vectors, cf. https://stackoverflow.com/questions/2371436/evaluating-a-mathematical-expression-in-a-string/2371789
|
||||
parser.add_argument('--lattice_base', nargs=4, action='store', type=float, required=True, help='Lattice basis vectors x1, y1, x2, y2')
|
||||
parser.add_argument('--particle', '-p', nargs='+', action=make_action_sharedlist('particle', 'particlespec'), help='Particle label, coordinates x,y, and (optionally) path to the T-Matrix.')
|
||||
parser.add_argument('--TMatrix', '-t', nargs='+', action=make_action_sharedlist('TMatrix_path', 'particlespec'), help='Path to TMatrix file')
|
||||
#parser.add_argument('--griddir', action='store', required=True, help='Path to the directory with precalculated translation operators')
|
||||
parser.add_argument('--output_prefix', action='store', required=True, help='Prefix to the npz output (will be appended frequency, hexside and chunkno)')
|
||||
#sizepar = parser.add_mutually_exclusive_group(required=True)
|
||||
#DEL parser.add_argument('--hexside', action='store', type=float, required=True, help='Lattice hexagon size length')
|
||||
parser.add_argument('--plot_TMatrix', action='store_true', help='Visualise TMatrix on the first page of the output')
|
||||
#parser.add_argument('--SVD_output', action='store', help='Path to output singular value decomposition result')
|
||||
parser.add_argument('--maxlayer', action='store', type=int, default=100, help='How far to sum the lattice points to obtain the dispersion')
|
||||
parser.add_argument('--scp_to', action='store', metavar='N', type=str, help='SCP the output files to a given destination')
|
||||
parser.add_argument('--background_permittivity', action='store', type=float, default=1., help='Background medium relative permittivity (default 1)')
|
||||
parser.add_argument('--eVfreq', action='store', required=True, type=float, help='Frequency in eV')
|
||||
parser.add_argument('--kdensity', '--k_density', action='store', type=int, default=33, help='Number of k-points per x-axis segment FIXME DESCRIPTION')
|
||||
parser.add_argument('--bz_coverage', action='store', type=float, default=1., help='Brillouin zone coverage in relative length (default 1 for whole 1. BZ)')
|
||||
parser.add_argument('--bz_edge_width', action='store', type=float, default=0., help='Width of the more densely covered belt along the 1. BZ edge in relative lengths')
|
||||
parser.add_argument('--bz_edge_factor', action='store', type=float, default=8., help='Relative density of the belt along the 1. BZ edge w.r.t. k_density (default==8)')
|
||||
parser.add_argument('--bz_edge_twoside', action='store_true', help='Compute also the parts of the densely covered edge belt outside the 1. BZ')
|
||||
parser.add_argument('--bz_corner_width', action='store', type=float, default=0., help='Size of the more densely covered subcell along the 1. BZ corners in relative lengths')
|
||||
parser.add_argument('--bz_corner_factor', action='store', type=float, default=16., help='Relative density of the subcell along the 1. BZ corner w.r.t. k_density (default==16)')
|
||||
parser.add_argument('--bz_corner_twoside', action='store_true', help='Compute also the parts of the densely covered subcell outside the 1. BZ')
|
||||
|
||||
parser.add_argument('--chunklen', action='store', type=int, default=1000, help='Number of k-points per output file (default 1000)')
|
||||
parser.add_argument('--lMax', action=make_action_sharedlist('lMax', 'particlespec'), nargs=+, help='Override lMax from the TMatrix file')
|
||||
#TODO some more sophisticated x axis definitions
|
||||
parser.add_argument('--gaussian', action='store', type=float, metavar='σ', help='Use a gaussian envelope for weighting the interaction matrix contributions (depending on the distance), measured in unit cell lengths (?) FIxME).')
|
||||
parser.add_argument('--verbose', '-v', action='count', help='Be verbose (about computation times, mostly)')
|
||||
popgrp=parser.add_argument_group(title='Operations')
|
||||
popgrp.add_argument('--tr', dest='ops', nargs='+', action=make_action_sharedlist('tr', 'ops'), default=list()) # the default value for dest can be set once
|
||||
popgrp.add_argument('--sym', dest='ops', nargs='+', action=make_action_sharedlist('sym', 'ops'))
|
||||
#popgrp.add_argument('--mult', dest='ops', nargs=3, metavar=('INCSPEC', 'SCATSPEC', 'MULTIPLIER'), action=make_action_sharedlist('mult', 'ops'))
|
||||
#popgrp.add_argument('--multl', dest='ops', nargs=3, metavar=('INCL[,INCL,...]', 'SCATL[,SCATL,...]', 'MULTIPLIER'), action=make_action_sharedlist('multl', 'ops'))
|
||||
parser.add_argument('--frequency_multiplier', action='store', type=float, default=1., help='Multiplies the frequencies in the TMatrix file by a given factor.')
|
||||
pargs=parser.parse_args()
|
||||
print(pargs)
|
||||
|
||||
exit(0) ###
|
||||
|
||||
maxlayer=pargs.maxlayer
|
||||
#DEL hexside=pargs.hexside
|
||||
eVfreq = pargs.eVfreq
|
||||
freq = eVfreq*eV/hbar
|
||||
verbose=pargs.verbose
|
||||
|
||||
#DEL TMatrix_file = pargs.TMatrix
|
||||
|
||||
epsilon_b = pargs.background_permittivity #2.3104
|
||||
gaussianSigma = pargs.gaussian if pargs.gaussian else None # hexside * 222 / 7
|
||||
interpfreqfactor = pargs.frequency_multiplier
|
||||
scp_dest = pargs.scp_to if pargs.scp_to else None
|
||||
kdensity = pargs.kdensity
|
||||
chunklen = pargs.chunklen
|
||||
|
||||
#### Nanoparticle position and T-matrix path parsing ####
|
||||
TMatrix_paths = dict()
|
||||
lMax_overrides = dict()
|
||||
default_TMatrix_path = None
|
||||
default_lMax_override = None
|
||||
if not any((arg_type == 'particle') in (arg_type, arg_content) for in pargs.particlespec):
|
||||
# no particles positions given: suppose only one per unit cell, in the cell origin
|
||||
positions = {None: (0.0)}
|
||||
else:
|
||||
positions = dict()
|
||||
for arg_type, arg_content in pargs.particlespec:
|
||||
if arg_type == 'particle' # --particle option
|
||||
if 3 <= len(arg_content) <= 4:
|
||||
try:
|
||||
positions[arg_content[0]] = (float(arg_content[1]), float(arg_content[2]))
|
||||
except ValueError as e:
|
||||
e.args += ("second and third argument of --particle must be valid floats, given: ", arg_content)
|
||||
raise
|
||||
if len(arg_content == 4):
|
||||
if arg_content[0] in TMatrix_paths:
|
||||
warnings.warn('T-matrix path for particle \'%s\' already specified.'
|
||||
'Overriding with the last value.' % arg_content[0], SyntaxWarning)
|
||||
TMatrix_paths[arg_content[0]] = arg_content[3]
|
||||
|
||||
else:
|
||||
raise ValueError("--particle expects 3 or 4 arguments, %d given: " % len(arg_content), arg_content)
|
||||
elif arg_type == 'TMatrix_path': # --TMatrix option
|
||||
if len(arg_content) == 1: # --TMatrix default_path
|
||||
if default_TMatrix_path is not None:
|
||||
warnings.warn('Default T-matrix path already specified. Overriding with the last value.', SyntaxWarning)
|
||||
default_TMatrix_path = arg_content[0]
|
||||
elif len(arg_content) > 1: # --TMatrix label [label2 [...]] path
|
||||
for label in arg_content[:-1]:
|
||||
if label in TMatrix_paths.keys():
|
||||
warnings.warn('T-matrix path for particle \'%s\' already specified.'
|
||||
'Overriding with the last value.' % label, SyntaxWarning)
|
||||
TMatrix_paths[label] = arg_content[-1]
|
||||
elif arg_type == 'lMax': # --lMax option
|
||||
if len(arg_content) == 1: # --lMax default_lmax_override
|
||||
if default_lMax_override is not None:
|
||||
warnings.warn('Default lMax override value already specified. Overriding the last value.', SyntaxWarning)
|
||||
default_lMax_override = int(arg_content[-1])
|
||||
else:
|
||||
for label in arg_content[:-1]:
|
||||
if label in lMax_overrides.keys:
|
||||
warnings.warn('lMax override for particle \'%s\' already specified.'
|
||||
'overriding with the last value.' % label, SyntaxWarning)
|
||||
lMax_overrides[label] = int(arg_content[-1])
|
||||
else: assert False, 'unknown option type'
|
||||
# Check the info from positions and TMatrix_paths and lMax_overrides
|
||||
if not set(TMatrix_paths.keys()) <= set(positions.keys()):
|
||||
raise ValueError("T-Matrix path(s) for particle(s) labeled %s was given, but not their positions"
|
||||
% str(set(TMatrix_paths.keys()) - set(positions.keys())))
|
||||
if not set(lMax_overrides.keys()) <= set(positions.keys()):
|
||||
raise ValueError("lMax override(s) for particle(s) labeled %s was given, but not their positions"
|
||||
%str(set(lMax_overrides.keys()) - set(positions.keys())))
|
||||
if (set(TMatrix_paths.keys()) != set(positions.keys())) and default_TMatrix_path is None:
|
||||
raise ValueError("Position(s) of particles(s) labeled %s was given without their T-matrix"
|
||||
" and no default T-matrix was specified"
|
||||
% str(set(positions.keys()) - set(TMatrix_paths_keys())))
|
||||
for path in TMatrix_paths.values():
|
||||
if not os.path.exists(path):
|
||||
raise ValueError("Cannot access T-matrix file %s. Does it exist?" % path)
|
||||
|
||||
# Assign (pre-parse) the T-matrix operations to individual particles
|
||||
ops = dict()
|
||||
for label in positions.keys(): ops[label] = list()
|
||||
for optype, arg_content in pargs.ops:
|
||||
# if, no label given, apply to all, otherwise on the specifield particles
|
||||
for label in (positions.keys() if len(arg_content) == 1 else arg_content[:-1]):
|
||||
try:
|
||||
ops[label].append((optype, arg_content[-1]))
|
||||
except KeyError as e:
|
||||
e.args += 'Specified operation on undefined particle labeled \'%s\'' % label
|
||||
raise
|
||||
|
||||
print(sys.stderr, "ops: ", ops) #DEBUG
|
||||
|
||||
#### Collect all the info about the particles / their T-matrices into one list ####
|
||||
# Enumerate and assign all the _different_ T-matrices (without any intelligent group-theory checking, though)
|
||||
TMatrix_specs = dict((spec, number)
|
||||
for (number, spec) in enumerate(set(
|
||||
(lMax_overrides[label] if label in lMax_overrides.keys() else None,
|
||||
TMatrix_paths[label],
|
||||
tuple(ops[label]))
|
||||
for label in positions.keys()
|
||||
)))
|
||||
# particles_specs contains (label, (xpos, ypos), tmspec_index per element)
|
||||
particles_specs = [(label, positions(label),
|
||||
TMatrix_specs[(lMax_overrides[label] if label in lMax_overrides.keys() else None,
|
||||
TMatrix_paths[label],
|
||||
tuple(ops[label]))]
|
||||
) for label in positions.keys()]
|
||||
|
||||
# -----------------finished basic CLI parsing (except for op arguments) ------------------
|
||||
from qpms.timetrack import _time_b, _time_e
|
||||
btime=_time_b(verbose)
|
||||
|
||||
import qpms
|
||||
import numpy as np
|
||||
import os, sys, warnings, math
|
||||
from scipy import interpolate
|
||||
nx = None
|
||||
s3 = math.sqrt(3)
|
||||
|
||||
|
||||
# specifikace T-matice zde
|
||||
cdn = c/ math.sqrt(epsilon_b)
|
||||
TMatrices_orig, freqs_orig, freqs_weirdunits_orig, lMaxTM = qpms.loadScuffTMatrices(TMatrix_file)
|
||||
lMax = lMaxTM
|
||||
if pargs.lMax:
|
||||
lMax = pargs.lMax if pargs.lMax else lMaxTM
|
||||
my, ny = qpms.get_mn_y(lMax)
|
||||
nelem = len(my)
|
||||
if pargs.lMax: #force commandline specified lMax
|
||||
TMatrices_orig = TMatrices_orig[...,0:nelem,:,0:nelem]
|
||||
|
||||
TMatrices = np.array(np.broadcast_to(TMatrices_orig[:,nx,:,:,:,:],(len(freqs_orig),2,2,nelem,2,nelem)) )
|
||||
|
||||
#TMatrices[:,:,:,:,:,ny==3] *= factor13inc
|
||||
#TMatrices[:,:,:,ny==3,:,:] *= factor13scat
|
||||
xfl = qpms.xflip_tyty(lMax)
|
||||
yfl = qpms.yflip_tyty(lMax)
|
||||
zfl = qpms.zflip_tyty(lMax)
|
||||
c2rot = qpms.apply_matrix_left(qpms.yflip_yy(3),qpms.xflip_yy(3),-1)
|
||||
|
||||
reCN = re.compile('(\d*)C(\d+)')
|
||||
#TODO C nekonečno
|
||||
|
||||
for op in ops:
|
||||
if op[0] == 'all':
|
||||
targets = (0,1)
|
||||
elif isinstance(op[0],int):
|
||||
targets = (op[0],)
|
||||
else:
|
||||
targets = op[0]
|
||||
|
||||
if op[1] == 'sym':
|
||||
mCN = reCN.match(op[2]) # Fuck van Rossum for not having assignments inside expressions
|
||||
if op[2] == 'σ_z':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(zfl,qpms.apply_ndmatrix_left(zfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'σ_y':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(yfl,qpms.apply_ndmatrix_left(yfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'σ_x':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_ndmatrix_left(xfl,qpms.apply_ndmatrix_left(xfl, TMatrices[:,t], (-4,-3)),(-2,-1)))/2
|
||||
elif op[2] == 'C2': # special case of the latter
|
||||
for t in targets:
|
||||
TMatrices[:,t] = (TMatrices[:,t] + qpms.apply_matrix_left(c2rot,qpms.apply_matrix_left(c2rot, TMatrices[:,t], -3),-1))/2
|
||||
elif mCN:
|
||||
rotN = int(mCN.group(2))
|
||||
TMatrix_contribs = np.empty((rotN,TMatrices.shape[0],2,nelem,2,nelem), dtype=np.complex_)
|
||||
for t in targets:
|
||||
for i in range(rotN):
|
||||
rotangle = 2*np.pi*i / rotN
|
||||
rot = qpms.WignerD_yy_fromvector(lMax,np.array([0,0,rotangle]))
|
||||
rotinv = qpms.WignerD_yy_fromvector(lMax,np.array([0,0,-rotangle]))
|
||||
TMatrix_contribs[i] = qpms.apply_matrix_left(rot,qpms.apply_matrix_left(rotinv, TMatrices[:,t], -3),-1)
|
||||
TMatrices[:,t] = np.sum(TMatrix_contribs, axis=0) / rotN
|
||||
else:
|
||||
raise ValueError('\'%d\' is not an implemented symmetry operation' % op[2])
|
||||
elif op[1] == 'tr':
|
||||
mCN = reCN.match(op[2]) # Fuck van Rossum for not having assignments inside expressions
|
||||
if op[2] == 'σ_z':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(zfl,qpms.apply_ndmatrix_left(zfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'σ_y':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(yfl,qpms.apply_ndmatrix_left(yfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'σ_x':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_ndmatrix_left(xfl,qpms.apply_ndmatrix_left(xfl, TMatrices[:,t], (-4,-3)),(-2,-1))
|
||||
elif op[2] == 'C2':
|
||||
for t in targets:
|
||||
TMatrices[:,t] = qpms.apply_matrix_left(c2rot,qpms.apply_matrix_left(c2rot, TMatrices[:,t], -3),-1)
|
||||
elif mCN:
|
||||
rotN = int(mCN.group(2))
|
||||
power = int(mCN.group(1)) if mCN.group(1) else 1
|
||||
TMatrix_contribs = np.empty((rotN,TMatrices.shape[0],2,nelem,2,nelem), dtype=np.complex_)
|
||||
for t in targets:
|
||||
rotangle = 2*np.pi*power/rotN
|
||||
rot = qpms.WignerD_yy_fromvector(lMax, np.array([0,0,rotangle]))
|
||||
rotinv = qpms.WignerD_yy_fromvector(lMax, np.array([0,0,-rotangle]))
|
||||
TMatrices[:,t] = qpms.apply_matrix_left(rot, qpms.apply_matrix_left(rotinv, TMatrices[:,t], -3),-1)
|
||||
else:
|
||||
raise ValueError('\'%d\' is not an implemented T-matrix transformation operation' % op[2])
|
||||
elif op[1] == 'copy':
|
||||
raise # not implemented
|
||||
elif op[1] == 'mult':
|
||||
raise # not implemented
|
||||
elif op[1] == 'multl':
|
||||
incy = np.full((nelem,), False, dtype=bool)
|
||||
for incl in op[2][0].split(','):
|
||||
l = int(incl)
|
||||
incy += (l == ny)
|
||||
scaty = np.full((nelem,), False, dtype=bool)
|
||||
for scatl in op[2][1].split(','):
|
||||
l = int(scatl)
|
||||
scaty += (l == ny)
|
||||
for t in targets:
|
||||
TMatrices[np.ix_(np.arange(TMatrices.shape[0]),np.array([t]),np.array([0,1]),scaty,np.array([0,1]),incy)] *= float(op[2][2])
|
||||
else:
|
||||
raise #unknown operation; should not happen
|
||||
|
||||
TMatrices_interp = interpolate.interp1d(freqs_orig*interpfreqfactor, TMatrices, axis=0, kind='linear',fill_value="extrapolate")
|
||||
|
||||
klist_full = qpms.generate_trianglepoints(kdensity, v3d=True, include_origin=True)*3*math.pi/(3*kdensity*hexside)
|
||||
TMatrices_om = TMatrices_interp(freq)
|
||||
|
||||
chunkn = math.ceil(klist_full.shape[0] / chunklen)
|
||||
|
||||
if verbose:
|
||||
print('Evaluating %d k-points in %d chunks' % (klist_full.shape[0], chunkn), file = sys.stderr)
|
||||
sys.stderr.flush()
|
||||
|
||||
metadata = np.array({
|
||||
'lMax' : lMax,
|
||||
'maxlayer' : maxlayer,
|
||||
'gaussianSigma' : gaussianSigma,
|
||||
'epsilon_b' : epsilon_b,
|
||||
'hexside' : hexside,
|
||||
'chunkn' : chunkn,
|
||||
'TMatrix_file' : TMatrix_file,
|
||||
'ops' : ops,
|
||||
})
|
||||
|
||||
for chunki in range(chunkn):
|
||||
svdout = '%s_%dnm_%.4f_c%03d.npz' % (pargs.output_prefix, hexside/1e-9, eVfreq, chunki)
|
||||
|
||||
klist = klist_full[chunki * chunklen : (chunki + 1) * chunklen]
|
||||
|
||||
svdres = qpms.hexlattice_zsym_getSVD(lMax=lMax, TMatrices_om=TMatrices_om, epsilon_b=epsilon_b, hexside=hexside, maxlayer=maxlayer,
|
||||
omega=freq, klist=klist, gaussianSigma=gaussianSigma, onlyNmin=False, verbose=verbose)
|
||||
|
||||
#((svUfullTElist, svSfullTElist, svVfullTElist), (svUfullTMlist, svSfullTMlist, svVfullTMlist)) = svdres
|
||||
|
||||
np.savez(svdout, omega = freq, klist = klist,
|
||||
metadata=metadata,
|
||||
uTE = svdres[0][0],
|
||||
vTE = svdres[0][2],
|
||||
sTE = svdres[0][1],
|
||||
uTM = svdres[1][0],
|
||||
vTM = svdres[1][2],
|
||||
sTM = svdres[1][1],
|
||||
|
||||
)
|
||||
svdres=None
|
||||
|
||||
if scp_dest:
|
||||
if svdout:
|
||||
subprocess.run(['scp', svdout, scp_dest])
|
||||
|
||||
_time_e(btime, verbose)
|
||||
#print(time.strftime("%H.%M:%S",time.gmtime(time.time()-begtime)))
|
|
@ -1,35 +0,0 @@
|
|||
import qpms
|
||||
import numpy as np
|
||||
from numpy import newaxis as nx
|
||||
import math
|
||||
import cmath
|
||||
import os
|
||||
from scipy.constants import c, e as eV, hbar
|
||||
s3 = math.sqrt(3)
|
||||
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("omega")
|
||||
#parser.add_argument("maxlayer")
|
||||
args = parser.parse_args()
|
||||
omega_eV = float(args.omega)
|
||||
|
||||
print(omega_eV)
|
||||
|
||||
epsilon_b = 2.3104
|
||||
hexside = 375e-9
|
||||
lMax = 3
|
||||
maxlayer = 222
|
||||
my, ny = qpms.get_mn_y(lMax)
|
||||
nelem = len(my)
|
||||
|
||||
omega = omega_eV * eV / hbar
|
||||
|
||||
k_0 = omega * math.sqrt(epsilon_b) / c
|
||||
|
||||
output_prefix = '/tmp/diracpoints-newdata2/%d/' % maxlayer
|
||||
|
||||
os.makedirs(output_prefix, exist_ok=True)
|
||||
qpms.hexlattice_precalc_AB_save(file=output_prefix+str(omega_eV), lMax=lMax, k_hexside=k_0*hexside,
|
||||
maxlayer=maxlayer, savepointinfo=True)
|
|
@ -0,0 +1,128 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import math
|
||||
from qpms.argproc import ArgParser, annotate_pdf_metadata
|
||||
|
||||
ap = ArgParser(['rectlattice2d', 'single_particle', 'single_lMax', 'omega_seq'])
|
||||
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")
|
||||
ap.add_argument("-s", "--singular_values", type=int, default=10, help="Number of singular values to plot")
|
||||
ap.add_argument("--D2", action='store_true', help="Use D2h symmetry even if the x and y periods are equal")
|
||||
|
||||
a=ap.parse_args()
|
||||
|
||||
import logging
|
||||
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
|
||||
|
||||
px, py = a.period
|
||||
|
||||
#Important! The particles are supposed to be of D2h/D4h symmetry
|
||||
thegroup = 'D4h' if px == py 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_m%s_bg%s_f(%g..%g..%g)eV_L%d_SVGamma" % (
|
||||
particlestr, px*1e9, py*1e9, str(a.material), str(a.background), *(a.eV_seq), a.lMax)
|
||||
logging.info("Default file prefix: %s" % defaultprefix)
|
||||
|
||||
|
||||
import numpy as np
|
||||
import qpms
|
||||
import warnings
|
||||
from qpms.cybspec import BaseSpec
|
||||
from qpms.cytmatrices import CTMatrix, TMatrixGenerator
|
||||
from qpms.qpms_c import Particle, pgsl_ignore_error
|
||||
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
|
||||
|
||||
# not used; TODO:
|
||||
irrep_labels = {"B2''":"$B_2''$",
|
||||
"B2'":"$B_2'$",
|
||||
"A1''":"$A_1''$",
|
||||
"A1'":"$A_1'$",
|
||||
"A2''":"$A_2''$",
|
||||
"B1''":"$B_1''$",
|
||||
"A2'":"$A_2'$",
|
||||
"B1'":"$B_1'$",
|
||||
"E'":"$E'$",
|
||||
"E''":"$E''$",}
|
||||
|
||||
dbgmsg_enable(DebugFlags.INTEGRATION)
|
||||
|
||||
a1 = ap.direct_basis[0]
|
||||
a2 = ap.direct_basis[1]
|
||||
|
||||
#Particle positions
|
||||
orig_x = [0]
|
||||
orig_y = [0]
|
||||
orig_xy = np.stack(np.meshgrid(orig_x,orig_y),axis=-1)
|
||||
|
||||
omegas = ap.omegas
|
||||
|
||||
logging.info("%d frequencies from %g to %g eV" % (len(omegas), omegas[0]/eh, omegas[-1]/eh))
|
||||
|
||||
bspec = BaseSpec(lMax = a.lMax)
|
||||
nelem = len(bspec)
|
||||
# The parameters here should probably be changed (needs a better qpms_c.Particle implementation)
|
||||
pp = Particle(orig_xy[0][0], ap.tmgen, bspec=bspec)
|
||||
|
||||
ss, ssw = ScatteringSystem.create([pp], ap.background_emg, omegas[0], latticebasis=ap.direct_basis)
|
||||
k = np.array([0.,0.,0])
|
||||
# Auxillary finite scattering system for irrep decomposition, quite a hack
|
||||
ss1, ssw1 = ScatteringSystem.create([pp], ap.background_emg, omegas[0],sym=FinitePointGroup(point_group_info[thegroup]))
|
||||
|
||||
wavenumbers = np.empty(omegas.shape)
|
||||
SVs = [None] * ss1.nirreps
|
||||
for iri in range(ss1.nirreps):
|
||||
SVs[iri] = np.empty(omegas.shape+(ss1.saecv_sizes[iri],))
|
||||
for i, omega in enumerate(omegas):
|
||||
ssw = ss(omega)
|
||||
wavenumbers[i] = ssw.wavenumber.real
|
||||
if ssw.wavenumber.imag:
|
||||
warnings.warn("Non-zero imaginary wavenumber encountered")
|
||||
with pgsl_ignore_error(15): # avoid gsl crashing on underflow; maybe not needed
|
||||
ImTW = ssw.modeproblem_matrix_full(k)
|
||||
for iri in range(ss1.nirreps):
|
||||
if ss1.saecv_sizes[iri] == 0:
|
||||
continue
|
||||
ImTW_packed = ss1.pack_matrix(ImTW, iri)
|
||||
SVs[iri][i] = np.linalg.svd(ImTW_packed, compute_uv = False)
|
||||
|
||||
outfile = defaultprefix + ".npz" if a.output is None else a.output
|
||||
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
|
||||
)
|
||||
logging.info("Saved to %s" % outfile)
|
||||
|
||||
|
||||
if a.plot or (a.plot_out is not None):
|
||||
import matplotlib
|
||||
matplotlib.use('pdf')
|
||||
from matplotlib import pyplot as plt
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(111)
|
||||
cc = plt.rcParams['axes.prop_cycle']()
|
||||
for iri in range(ss1.nirreps):
|
||||
cargs = next(cc)
|
||||
nlines = min(a.singular_values, ss1.saecv_sizes[iri])
|
||||
for i in range(nlines):
|
||||
ax.plot(omegas/eh, SVs[iri][:,-1-i],
|
||||
label= None if i else irrep_labels[ss1.irrep_names[iri]],
|
||||
**cargs)
|
||||
ax.set_ylim([0,1.1])
|
||||
ax.set_xlabel('$\hbar \omega / \mathrm{eV}$')
|
||||
ax.set_ylabel('Singular values')
|
||||
ax.legend()
|
||||
|
||||
plotfile = defaultprefix + ".pdf" if a.plot_out is None else a.plot_out
|
||||
with PdfPages(plotfile) as pdf:
|
||||
pdf.savefig(fig)
|
||||
annotate_pdf_metadata(pdf, scriptname='infiniterectlat-k0realfreqsvd.py')
|
||||
|
||||
exit(0)
|
||||
|
|
@ -1,13 +1,11 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import math
|
||||
from qpms.argproc import ArgParser
|
||||
pi = math.pi
|
||||
from qpms.argproc import ArgParser, annotate_pdf_metadata
|
||||
|
||||
ap = ArgParser(['rectlattice2d', 'single_particle', 'single_lMax', 'single_omega'])
|
||||
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 = ArgParser(['rectlattice2d', 'single_particle', 'single_lMax', '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("-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")
|
||||
#ap.add_argument("-g", "--save-gradually", action='store_true', help="saves the partial result after computing each irrep")
|
||||
|
@ -18,17 +16,9 @@ a=ap.parse_args()
|
|||
import logging
|
||||
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
|
||||
|
||||
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_m%s_n%g_angles(%g_%g)_Ey_f%geV_L%d_cn%d" % (
|
||||
particlestr, px*1e9, py*1e9, 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)
|
||||
|
||||
|
||||
import numpy as np
|
||||
import qpms
|
||||
from qpms.qpms_p import cart2sph, sph2cart, sph_loccart2cart, sph_loccart_basis
|
||||
import warnings
|
||||
from qpms.cybspec import BaseSpec
|
||||
from qpms.cytmatrices import CTMatrix, TMatrixGenerator
|
||||
|
@ -40,6 +30,15 @@ eh = eV/hbar
|
|||
|
||||
dbgmsg_enable(DebugFlags.INTEGRATION)
|
||||
|
||||
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_m%s_bg%s_φ%g_θ(%g_%g)π_ψ%gπ_χ%gπ_f%s_L%d" % (
|
||||
particlestr, px*1e9, py*1e9, 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)
|
||||
logging.info("Default file prefix: %s" % defaultprefix)
|
||||
|
||||
|
||||
a1 = ap.direct_basis[0]
|
||||
a2 = ap.direct_basis[1]
|
||||
|
||||
|
@ -48,72 +47,173 @@ orig_x = [0]
|
|||
orig_y = [0]
|
||||
orig_xy = np.stack(np.meshgrid(orig_x,orig_y),axis=-1)
|
||||
|
||||
omega = ap.omega
|
||||
|
||||
bspec = BaseSpec(lMax = a.lMax)
|
||||
# The parameters here should probably be changed (needs a better qpms_c.Particle implementation)
|
||||
pp = Particle(orig_xy[0][0], ap.tmgen, bspec=bspec)
|
||||
par = [pp]
|
||||
|
||||
|
||||
ss, ssw = ScatteringSystem.create(par, ap.background_emg, omega, latticebasis = ap.direct_basis)
|
||||
ss, ssw = ScatteringSystem.create(par, ap.background_emg, ap.allomegas[0], latticebasis = ap.direct_basis)
|
||||
|
||||
if ssw.wavenumber.imag != 0:
|
||||
warnings.warn("The background medium wavenumber has non-zero imaginary part. Don't expect meaningful results for cross sections.")
|
||||
wavenumber = ssw.wavenumber.real
|
||||
|
||||
sinalpha_list = np.linspace(a.kx_lim[0],a.kx_lim[1],a.N)
|
||||
## Plane wave data
|
||||
a.theta = np.array(a.theta)
|
||||
dir_sph_list = np.stack((np.broadcast_to(1, a.theta.shape), a.theta, np.broadcast_to(a.phi, a.theta.shape)), axis=-1)
|
||||
sψ, cψ = math.sin(a.psi), math.cos(a.psi)
|
||||
sχ, cχ = math.sin(a.chi), math.cos(a.chi)
|
||||
E_sph = (0., cψ*cχ + 1j*sψ*sχ, sψ*cχ + 1j*cψ*sχ)
|
||||
|
||||
# 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
|
||||
dir_cart_list = sph2cart(dir_sph_list)
|
||||
E_cart_list = sph_loccart2cart(E_sph, dir_sph_list)
|
||||
|
||||
σ_ext_list = np.empty((a.N,), dtype=float)
|
||||
σ_scat_list = np.empty((a.N,), dtype=float)
|
||||
nfreq = len(ap.allomegas)
|
||||
ndir = len(dir_sph_list)
|
||||
|
||||
k_cart_arr = np.empty((nfreq, ndir, 3), dtype=float)
|
||||
wavenumbers = np.empty((nfreq,), dtype=float)
|
||||
|
||||
σ_ext_arr = np.empty((nfreq,ndir), dtype=float)
|
||||
σ_scat_arr = np.empty((nfreq,ndir), dtype=float)
|
||||
|
||||
with pgsl_ignore_error(15): # avoid gsl crashing on underflow
|
||||
for j in range(a.N):
|
||||
k_cart = k_cart_list[j]
|
||||
blochvector = (k_cart[0], k_cart[1], 0)
|
||||
# the following two could be calculated only once, but probably not a big deal
|
||||
LU = ssw.scatter_solver(k=blochvector)
|
||||
ã = ss.planewave_full(k_cart=k_cart, E_cart=E_cart_list[j])
|
||||
Tã = ssw.apply_Tmatrices_full(ã)
|
||||
f = LU(Tã)
|
||||
for i, omega in enumerate(ap.allomegas):
|
||||
if i != 0:
|
||||
ssw = ss(omega)
|
||||
if ssw.wavenumber.imag != 0:
|
||||
warnings.warn("The background medium wavenumber has non-zero imaginary part. Don't expect meaningful results for cross sections.")
|
||||
wavenumber = ssw.wavenumber.real
|
||||
wavenumbers[i] = wavenumber
|
||||
|
||||
σ_ext_list[j] = -np.vdot(ã, f).real/wavenumber**2
|
||||
translation_matrix = ssw.translation_matrix_full(blochvector=blochvector) + np.eye(ss.fecv_size)
|
||||
σ_scat_list[j] = np.vdot(f,np.dot(translation_matrix, f)).real/wavenumber**2
|
||||
k_sph_list = np.array(dir_sph_list, copy=True)
|
||||
k_sph_list[:,0] = wavenumber
|
||||
|
||||
σ_abs_list = σ_ext_list - σ_scat_list
|
||||
k_cart_arr[i] = sph2cart(k_sph_list)
|
||||
|
||||
|
||||
for j in range(ndir):
|
||||
k_cart = k_cart_arr[i,j]
|
||||
blochvector = (k_cart[0], k_cart[1], 0)
|
||||
# the following two could be calculated only once, but probably not a big deal
|
||||
LU = ssw.scatter_solver(k=blochvector)
|
||||
ã = ss.planewave_full(k_cart=k_cart, E_cart=E_cart_list[j])
|
||||
Tã = ssw.apply_Tmatrices_full(ã)
|
||||
f = LU(Tã)
|
||||
|
||||
σ_ext_arr[i,j] = -np.vdot(ã, f).real/wavenumber**2
|
||||
translation_matrix = ssw.translation_matrix_full(blochvector=blochvector) + np.eye(ss.fecv_size)
|
||||
σ_scat_arr[i,j] = np.vdot(f,np.dot(translation_matrix, f)).real/wavenumber**2
|
||||
|
||||
σ_abs_arr = σ_ext_arr - σ_scat_arr
|
||||
|
||||
outfile = defaultprefix + ".npz" if a.output is None else a.output
|
||||
np.savez(outfile, meta=vars(a), sinalpha=sinalpha_list, k_cart = k_cart_list, E_cart=E_cart_list, σ_ext=σ_ext_list,σ_abs=σ_abs_list,σ_scat=σ_scat_list, omega=omega, wavenumber=wavenumber, unitcell_area=ss.unitcell_volume
|
||||
np.savez(outfile, meta={**vars(a), 'qpms_version' : qpms.__version__()}, dir_sph=dir_sph_list, k_cart = k_cart_arr, omega = ap.allomegas, E_cart = E_cart_list, wavenumbers= wavenumbers, σ_ext=σ_ext_arr,σ_abs=σ_abs_arr,σ_scat=σ_scat_arr, unitcell_area=ss.unitcell_volume
|
||||
)
|
||||
logging.info("Saved to %s" % outfile)
|
||||
|
||||
|
||||
if a.plot or (a.plot_out is not None):
|
||||
import matplotlib
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
matplotlib.use('pdf')
|
||||
from matplotlib import pyplot as plt
|
||||
from scipy.interpolate import griddata
|
||||
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(111)
|
||||
ax.plot(sinalpha_list, σ_ext_list*1e12,label='$\sigma_\mathrm{ext}$')
|
||||
ax.plot(sinalpha_list, σ_scat_list*1e12, label='$\sigma_\mathrm{scat}$')
|
||||
ax.plot(sinalpha_list, σ_abs_list*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)
|
||||
with PdfPages(plotfile) as pdf:
|
||||
ipm = 'nearest'
|
||||
sintheta = np.sin(a.theta)
|
||||
if False: #len(ap.omega_ranges) != 0:
|
||||
# angle plot ---------------------------------
|
||||
fig = plt.figure(figsize=(210/25.4, 297/25.4))
|
||||
vmax = max(np.amax(σ_ext_arr), np.amax(σ_scat_arr), np.amax(σ_abs_arr))
|
||||
vmin = min(np.amin(σ_ext_arr), np.amin(σ_scat_arr), np.amin(σ_abs_arr))
|
||||
|
||||
ax = fig.add_subplot(311)
|
||||
ax.pcolormesh(a.theta, ap.allomegas/eh, σ_ext_arr, vmin=vmin, vmax=vmax)
|
||||
ax.set_xlabel('$\\theta$')
|
||||
ax.set_ylabel('$\\hbar\\omega / \\mathrm{eV}$')
|
||||
ax.set_title('$\\sigma_\\mathrm{ext}$')
|
||||
|
||||
ax = fig.add_subplot(312)
|
||||
ax.pcolormesh(a.theta, ap.allomegas/eh, σ_scat_arr, vmin=vmin, vmax=vmax)
|
||||
ax.set_xlabel('$\\theta$')
|
||||
ax.set_ylabel('$\\hbar\\omega / \\mathrm{eV}$')
|
||||
ax.set_title('$\\sigma_\\mathrm{scat}$')
|
||||
|
||||
ax = fig.add_subplot(313)
|
||||
im = ax.pcolormesh(a.theta, ap.allomegas/eh, σ_abs_arr, vmin=vmin, vmax=vmax)
|
||||
ax.set_xlabel('$\\theta$')
|
||||
ax.set_ylabel('$\\hbar\\omega / \\mathrm{eV}$')
|
||||
ax.set_title('$\\sigma_\\mathrm{abs}$')
|
||||
|
||||
|
||||
fig.subplots_adjust(right=0.8)
|
||||
fig.colorbar(im, cax = fig.add_axes([0.85, 0.15, 0.05, 0.7]))
|
||||
|
||||
pdf.savefig(fig)
|
||||
plt.close(fig)
|
||||
|
||||
if len(ap.omega_ranges) != 0:
|
||||
# "k-space" plot -----------------------------
|
||||
domega = np.amin(np.diff(ap.allomegas))
|
||||
dsintheta = np.amin(abs(np.diff(sintheta)))
|
||||
dk = dsintheta * wavenumbers[0]
|
||||
|
||||
# target image grid
|
||||
grid_y, grid_x = np.mgrid[ap.allomegas[0] : ap.allomegas[-1] : domega, np.amin(sintheta) * wavenumbers[-1] : np.amax(sintheta) * wavenumbers[-1] : dk]
|
||||
imextent = (np.amin(sintheta) * wavenumbers[-1] / 1e6, np.amax(sintheta) * wavenumbers[-1] / 1e6, ap.allomegas[0] / eh, ap.allomegas[-1] / eh)
|
||||
|
||||
# source coordinates for griddata
|
||||
ktheta = sintheta[None, :] * wavenumbers[:, None]
|
||||
omegapoints = np.broadcast_to(ap.allomegas[:, None], ktheta.shape)
|
||||
points = np.stack( (ktheta.flatten(), omegapoints.flatten()), axis = -1)
|
||||
|
||||
fig = plt.figure(figsize=(210/25.4, 297/25.4))
|
||||
vmax = np.amax(σ_ext_arr)
|
||||
|
||||
ax = fig.add_subplot(311)
|
||||
grid_z = griddata(points, σ_ext_arr.flatten(), (grid_x, grid_y), method = ipm)
|
||||
ax.imshow(grid_z, extent = imextent, origin = 'lower', vmin = 0, vmax = vmax, aspect = 'auto', interpolation='none')
|
||||
ax.set_xlabel('$k_\\theta / \\mathrm{\\mu m^{-1}}$')
|
||||
ax.set_ylabel('$\\hbar\\omega / \\mathrm{eV}$')
|
||||
ax.set_title('$\\sigma_\\mathrm{ext}$')
|
||||
|
||||
ax = fig.add_subplot(312)
|
||||
grid_z = griddata(points, σ_scat_arr.flatten(), (grid_x, grid_y), method = ipm)
|
||||
ax.imshow(grid_z, extent = imextent, origin = 'lower', vmin = 0, vmax = vmax, aspect = 'auto', interpolation='none')
|
||||
ax.set_xlabel('$k_\\theta / \\mathrm{\\mu m^{-1}}$')
|
||||
ax.set_ylabel('$\\hbar\\omega / \\mathrm{eV}$')
|
||||
ax.set_title('$\\sigma_\\mathrm{scat}$')
|
||||
|
||||
ax = fig.add_subplot(313)
|
||||
grid_z = griddata(points, σ_abs_arr.flatten(), (grid_x, grid_y), method = ipm)
|
||||
im = ax.imshow(grid_z, extent = imextent, origin = 'lower', vmin = 0, vmax = vmax, aspect = 'auto', interpolation='none')
|
||||
ax.set_xlabel('$k_\\theta / \\mathrm{\\mu m^{-1}}$')
|
||||
ax.set_ylabel('$\\hbar\\omega / \\mathrm{eV}$')
|
||||
ax.set_title('$\\sigma_\\mathrm{abs}$')
|
||||
|
||||
fig.subplots_adjust(right=0.8)
|
||||
fig.colorbar(im, cax = fig.add_axes([0.85, 0.15, 0.05, 0.7]))
|
||||
|
||||
pdf.savefig(fig)
|
||||
plt.close(fig)
|
||||
|
||||
for omega in ap.omega_singles:
|
||||
i = np.searchsorted(ap.allomegas, omega)
|
||||
|
||||
fig = plt.figure()
|
||||
fig.suptitle("%g eV" % (omega / eh))
|
||||
ax = fig.add_subplot(111)
|
||||
sintheta = np.sin(a.theta)
|
||||
ax.plot(sintheta, σ_ext_arr[i]*1e12,label='$\sigma_\mathrm{ext}$')
|
||||
ax.plot(sintheta, σ_scat_arr[i]*1e12, label='$\sigma_\mathrm{scat}$')
|
||||
ax.plot(sintheta, σ_abs_arr[i]*1e12, label='$\sigma_\mathrm{abs}$')
|
||||
ax.legend()
|
||||
ax.set_xlabel('$\sin\\theta$')
|
||||
ax.set_ylabel('$\sigma/\mathrm{\mu m^2}$')
|
||||
|
||||
pdf.savefig(fig)
|
||||
plt.close(fig)
|
||||
annotate_pdf_metadata(pdf)
|
||||
exit(0)
|
||||
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import math
|
||||
from qpms.argproc import ArgParser, sfloat, annotate_pdf_metadata
|
||||
|
||||
ap = ArgParser(['const_real_background', 'lattice2d', 'multi_particle']) # TODO general analytical background
|
||||
|
||||
ap.add_argument("-k", nargs=2, type=sfloat, 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)
|
||||
ap.add_argument("-o", "--output", type=str, required=False, help='output path (if not provided, will be generated automatically)')
|
||||
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("-T", "--residual-tolerance", type=float, default=2.)
|
||||
ap.add_argument("-N", type=int, default="150", help="Integration contour discretisation size")
|
||||
|
||||
|
||||
#TODO alternative specification of the contour by center and half-axes
|
||||
dospec = ap.add_argument_group("Eigenvalue search area by diffracted order specification", "Specification of eigenvalue search area by diffracted order number (requires constant real refractive index for background): the integration contour 'touches' the empty lattice band specified by -b, and its axis lying on the real axis reaches '-f'-way to the next diffractive order")
|
||||
dospec.add_argument("-d", "--band-index", type=int, help="Argument's absolute value determines the empty lattice band order (counted from 1), -/+ determines whether the eigenvalues are searched below/above that empty lattice band.", required=True)
|
||||
dospec.add_argument("-f", "--interval-factor", type=float, default=0.1, help="Relative length of the integration ellipse axis w.r.t. the interval between two empty lattice bands; this should be be less than 1.") #TODO check
|
||||
dospec.add_argument("-i", "--imaginary-aspect-ratio", type=float, default=1., help="Aspect ratio of the integration ellipse (Im/Re); this should not exceed 1/interval_factor.")
|
||||
|
||||
ap.add_argument("-P", "--plot", action='store_true', help="if -p not given, plot to a default path")
|
||||
ap.add_argument("-O", "--plot-out", type=str, required=False, help="path to plot output (optional)")
|
||||
|
||||
a = ap.parse_args()
|
||||
|
||||
a1 = ap.direct_basis[0]
|
||||
a2 = ap.direct_basis[1]
|
||||
|
||||
particlestr = "modes" # TODO particle string specifier or some hash, do this in argproc.py
|
||||
defaultprefix = "%s_basis%gnm_%gnm__%gnm_%gnm_n%g_b%+d_k(%g_%g)um-1_cn%d" % (
|
||||
particlestr, a1[0]*1e9, a1[1]*1e9, a2[0]*1e9, a2[1]*1e9, a.refractive_index, a.band_index, a.k[0]*1e-6, a.k[1]*1e-6, a.N)
|
||||
|
||||
|
||||
import logging
|
||||
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
|
||||
|
||||
import numpy as np
|
||||
import qpms
|
||||
from qpms.cybspec import BaseSpec
|
||||
from qpms.cytmatrices import CTMatrix
|
||||
from qpms.qpms_c import Particle, ScatteringSystem, empty_lattice_modes_xy
|
||||
from qpms.cymaterials import EpsMu, EpsMuGenerator, LorentzDrudeModel, lorentz_drude
|
||||
from qpms.constants import eV, hbar
|
||||
eh = eV/hbar
|
||||
|
||||
def inside_ellipse(point_xy, centre_xy, halfaxes_xy):
|
||||
x = point_xy[0] - centre_xy[0]
|
||||
y = point_xy[1] - centre_xy[1]
|
||||
ax = halfaxes_xy[0]
|
||||
ay = halfaxes_xy[1]
|
||||
return ((x/ax)**2 + (y/ay)**2) <= 1
|
||||
|
||||
beta = np.array(a.k)
|
||||
|
||||
if True: # TODO alternative specification of the contour by center and half-axes
|
||||
empty_freqs = empty_lattice_modes_xy(ap.background_epsmu, ap.reciprocal_basis2pi, np.array([0,0]), 1)
|
||||
empty_freqs = empty_lattice_modes_xy(ap.background_epsmu, ap.reciprocal_basis2pi, beta, (1+abs(a.band_index)) * empty_freqs[1])
|
||||
|
||||
# make the frequencies in the list unique
|
||||
empty_freqs = list(empty_freqs)
|
||||
i = 0
|
||||
while i < len(empty_freqs) - 1:
|
||||
if math.isclose(empty_freqs[i], empty_freqs[i+1], rel_tol=1e-13):
|
||||
del empty_freqs[i+1]
|
||||
else:
|
||||
i += 1
|
||||
|
||||
logging.info("Empty freqs: %s", str(empty_freqs))
|
||||
logging.info("Empty freqs (eV): %s", str([ff / eh for ff in empty_freqs]))
|
||||
if a.band_index > 0:
|
||||
top = empty_freqs[a.band_index]
|
||||
bottom = empty_freqs[a.band_index - 1]
|
||||
lebeta_om = bottom
|
||||
else: # a.band_index < 0
|
||||
top = empty_freqs[abs(a.band_index) - 1]
|
||||
bottom = empty_freqs[abs(a.band_index) - 2] if abs(a.band_index) > 1 else 0.
|
||||
lebeta_om = top
|
||||
#print(top,bottom,lebeta_om)
|
||||
freqradius = .5 * (top - bottom) * a.interval_factor
|
||||
|
||||
centfreq = bottom + freqradius if a.band_index > 0 else top - freqradius
|
||||
if freqradius == 0:
|
||||
raise ValueError("Integration contour radius is set to zero. Are you trying to look below the lowest empty lattice band at the gamma point?")
|
||||
|
||||
freqradius *= (1-1e-13) # to not totally touch the singularities
|
||||
|
||||
logging.info("Direct lattice basis: %s" % str(ap.direct_basis))
|
||||
logging.info("Reciprocal lattice basis: %s" % str(ap.reciprocal_basis2pi))
|
||||
|
||||
ss, ssw = ScatteringSystem.create(ap.get_particles(), ap.background_emg, centfreq, latticebasis=ap.direct_basis)
|
||||
|
||||
logging.info("Finding eigenvalues around %s (= %s eV)" % (str(centfreq), str(centfreq/eh)))
|
||||
logging.info("Real half-axis %s (= %s eV)" % (str(freqradius), str(freqradius/eh)))
|
||||
logging.info("Imaginary half-axis %s (= %s eV)" % (str(freqradius*a.imaginary_aspect_ratio), str(freqradius*a.imaginary_aspect_ratio/eh)))
|
||||
|
||||
with qpms.pgsl_ignore_error(15):
|
||||
res = ss.find_modes(centfreq, freqradius, freqradius * a.imaginary_aspect_ratio,
|
||||
blochvector = a.k, contour_points = a.N, rank_tol = a.rank_tolerance,
|
||||
res_tol = a.residual_tolerance, rank_min_sel = a.min_candidates)
|
||||
|
||||
logging.info("Eigenfrequencies found: %s" % str(res['eigval']))
|
||||
logging.info("Eigenfrequencies found (eV): %s" % str(res['eigval'] / eh))
|
||||
|
||||
res['inside_contour'] = inside_ellipse((res['eigval'].real, res['eigval'].imag),
|
||||
(centfreq.real, centfreq.imag), (freqradius, freqradius * a.imaginary_aspect_ratio))
|
||||
|
||||
#res['refractive_index_internal'] = [emg(om).n for om in res['eigval']]
|
||||
|
||||
#del res['omega'] If contour points are not needed...
|
||||
#del res['ImTW'] # not if dbg=false anyway
|
||||
outfile = defaultprefix + ".npz" if a.output is None else a.output
|
||||
np.savez(outfile, meta={**vars(a), 'qpms_version' : qpms.__version__()}, empty_freqs=np.array(empty_freqs),
|
||||
ss_positions=ss.positions, ss_fullvec_poffsets=ss.fullvec_poffsets,
|
||||
ss_fullvec_psizes=ss.fullvec_psizes,
|
||||
ss_bspecs_flat = np.concatenate(ss.bspecs),
|
||||
ss_lattice_basis=ss.lattice_basis, ss_reciprocal_basis = ss.reciprocal_basis,
|
||||
**res)
|
||||
logging.info("Saved to %s" % outfile)
|
||||
|
||||
|
||||
if a.plot or (a.plot_out is not None):
|
||||
if len(res['eigval']) == 0:
|
||||
logging.info("No eigenvalues found; nothing to plot")
|
||||
exit(1)
|
||||
imcut = np.linspace(0, -freqradius)
|
||||
recut1 = np.sqrt(lebeta_om**2+imcut**2) # incomplete Gamma-related cut
|
||||
recut2 = np.sqrt((lebeta_om/2)**2-imcut**2) + lebeta_om/2 # odd-power-lilgamma-related cut
|
||||
|
||||
import matplotlib
|
||||
matplotlib.use('pdf')
|
||||
from matplotlib import pyplot as plt
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(111,)
|
||||
#ax.plot(res['omega'].real/eh, res['omega'].imag/eh*1e3, ':') #res['omega'] not implemented in ScatteringSystem
|
||||
ax.add_artist(matplotlib.patches.Ellipse((centfreq.real/eh, centfreq.imag/eh*1e3),
|
||||
2*freqradius/eh, 2*freqradius*a.imaginary_aspect_ratio/eh*1e3, fill=False,
|
||||
ls=':'))
|
||||
ax.scatter(x=res['eigval'].real/eh, y=res['eigval'].imag/eh*1e3 , c = res['inside_contour']
|
||||
)
|
||||
ax.plot(recut1/eh, imcut/eh*1e3)
|
||||
ax.plot(recut2/eh, imcut/eh*1e3)
|
||||
for i,om in enumerate(res['eigval']):
|
||||
ax.annotate(str(i), (om.real/eh, om.imag/eh*1e3))
|
||||
xmin = np.amin(res['eigval'].real)/eh
|
||||
xmax = np.amax(res['eigval'].real)/eh
|
||||
xspan = xmax-xmin
|
||||
ymin = np.amin(res['eigval'].imag)/eh*1e3
|
||||
ymax = np.amax(res['eigval'].imag)/eh*1e3
|
||||
yspan = ymax-ymin
|
||||
ax.set_xlim([xmin-.1*xspan, xmax+.1*xspan])
|
||||
ax.set_ylim([ymin-.1*yspan, ymax+.1*yspan])
|
||||
ax.set_xlabel('$\hbar \Re \omega / \mathrm{eV}$')
|
||||
ax.set_ylabel('$\hbar \Im \omega / \mathrm{meV}$')
|
||||
|
||||
plotfile = defaultprefix + ".pdf" if a.plot_out is None else a.plot_out
|
||||
with PdfPages(plotfile) as pdf:
|
||||
pdf.savefig(fig)
|
||||
annotate_pdf_metadata(pdf, scriptname='lat2d_modes.py')
|
||||
|
||||
exit(0)
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import math
|
||||
from qpms.argproc import ArgParser, sfloat, annotate_pdf_metadata
|
||||
|
||||
ap = ArgParser(['background', 'lattice2d', 'multi_particle', 'omega_seq'])
|
||||
|
||||
ap.add_argument("-k", nargs=2, type=sfloat, 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("-g", "--little-group", type=str, default="trivial_g", help="Little group for subspace irrep classification", action="store")
|
||||
|
||||
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")
|
||||
ap.add_argument("-s", "--singular_values", type=int, default=10, help="Number of singular values to plot")
|
||||
|
||||
a=ap.parse_args()
|
||||
|
||||
import logging
|
||||
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
|
||||
|
||||
|
||||
#Important! The particles are supposed to be of D2h/D4h symmetry
|
||||
# thegroup = 'D4h' if px == py and not a.D2 else 'D2h'
|
||||
|
||||
a1 = ap.direct_basis[0]
|
||||
a2 = ap.direct_basis[1]
|
||||
|
||||
particlestr = "svdinterval" # TODO particle string specifier or some hash, do this in argproc.py
|
||||
defaultprefix = "%s_basis%gnm_%gnm__%gnm_%gnm_f(%g..%g..%g)eV_k%g_%g" % (
|
||||
particlestr, a1[0]*1e9, a1[1]*1e9, a2[0]*1e9, a2[1]*1e9, *(a.eV_seq), ap.k[0], ap.k[1])
|
||||
logging.info("Default file prefix: %s" % defaultprefix)
|
||||
|
||||
|
||||
import numpy as np
|
||||
import qpms
|
||||
import warnings
|
||||
from qpms.cybspec import BaseSpec
|
||||
from qpms.cytmatrices import CTMatrix, TMatrixGenerator
|
||||
from qpms.qpms_c import Particle, pgsl_ignore_error, empty_lattice_modes_xy
|
||||
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
|
||||
|
||||
# not used; TODO:
|
||||
irrep_labels = {"B2''":"$B_2''$",
|
||||
"B2'":"$B_2'$",
|
||||
"A1''":"$A_1''$",
|
||||
"A1'":"$A_1'$",
|
||||
"A2''":"$A_2''$",
|
||||
"B1''":"$B_1''$",
|
||||
"A2'":"$A_2'$",
|
||||
"B1'":"$B_1'$",
|
||||
"E'":"$E'$",
|
||||
"E''":"$E''$",}
|
||||
|
||||
dbgmsg_enable(DebugFlags.INTEGRATION)
|
||||
|
||||
|
||||
|
||||
omegas = ap.omegas
|
||||
|
||||
logging.info("%d frequencies from %g to %g eV" % (len(omegas), omegas[0]/eh, omegas[-1]/eh))
|
||||
|
||||
particles = ap.get_particles()
|
||||
|
||||
ss, ssw = ScatteringSystem.create(particles, ap.background_emg, omegas[0], latticebasis=ap.direct_basis)
|
||||
k = np.array([ap.k[0], ap.k[1], 0])
|
||||
# Auxillary finite scattering system for irrep decomposition, quite a hack
|
||||
ss1, ssw1 = ScatteringSystem.create(particles, ap.background_emg, omegas[0],sym=FinitePointGroup(point_group_info[ap.little_group]))
|
||||
|
||||
wavenumbers = np.empty(omegas.shape)
|
||||
SVs = [None] * ss1.nirreps
|
||||
for iri in range(ss1.nirreps):
|
||||
SVs[iri] = np.empty(omegas.shape+(ss1.saecv_sizes[iri],))
|
||||
for i, omega in enumerate(omegas):
|
||||
ssw = ss(omega)
|
||||
wavenumbers[i] = ssw.wavenumber.real
|
||||
if ssw.wavenumber.imag:
|
||||
warnings.warn("Non-zero imaginary wavenumber encountered")
|
||||
with pgsl_ignore_error(15): # avoid gsl crashing on underflow; maybe not needed
|
||||
ImTW = ssw.modeproblem_matrix_full(k)
|
||||
for iri in range(ss1.nirreps):
|
||||
ImTW_packed = ss1.pack_matrix(ImTW, iri)
|
||||
SVs[iri][i] = np.linalg.svd(ImTW_packed, compute_uv = False)
|
||||
|
||||
outfile = defaultprefix + ".npz" if a.output is None else a.output
|
||||
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
|
||||
)
|
||||
logging.info("Saved to %s" % outfile)
|
||||
|
||||
|
||||
if a.plot or (a.plot_out is not None):
|
||||
import matplotlib
|
||||
matplotlib.use('pdf')
|
||||
from matplotlib import pyplot as plt
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(111)
|
||||
cc = plt.rcParams['axes.prop_cycle']()
|
||||
for iri in range(ss1.nirreps):
|
||||
cargs = next(cc)
|
||||
nlines = min(a.singular_values, ss1.saecv_sizes[iri])
|
||||
for i in range(nlines):
|
||||
ax.plot(omegas/eh, SVs[iri][:,-1-i],
|
||||
label= None if i else irrep_labels.get(ss1.irrep_names[iri], ss1.irrep_names[iri]),
|
||||
**cargs)
|
||||
ax.set_ylim([0,1.1])
|
||||
if hasattr(ap, "background_epsmu"):
|
||||
xlim = ax.get_xlim()
|
||||
omegas_empty = empty_lattice_modes_xy(ap.background_epsmu, ap.reciprocal_basis2pi, k, omegas[-1])
|
||||
for om in omegas_empty:
|
||||
if om/eh > xlim[0] and om/eh < xlim[1]:
|
||||
ax.axvline(om/eh, ls=':')
|
||||
ax.set_xlabel('$\hbar \omega / \mathrm{eV}$')
|
||||
ax.set_ylabel('Singular values')
|
||||
ax.legend()
|
||||
|
||||
plotfile = defaultprefix + ".pdf" if a.plot_out is None else a.plot_out
|
||||
with PdfPages(plotfile) as pdf:
|
||||
pdf.savefig(fig)
|
||||
annotate_pdf_metadata(pdf, scriptname='lat2d_realfreqsvd.py')
|
||||
|
||||
exit(0)
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
from qpms import processWfiles_sameKs
|
||||
|
||||
npart = int(sys.argv[1])
|
||||
dest = sys.argv[2]
|
||||
srcs = sys.argv[3:]
|
||||
|
||||
processWfiles_sameKs(srcs, dest, f='d', nparticles=npart)
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
from qpms import processWfiles_sameKs
|
||||
|
||||
dest = sys.argv[1]
|
||||
srcs = sys.argv[2:]
|
||||
|
||||
processWfiles_sameKs(srcs, dest, f='d')
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
from qpms import processWfiles_sameKs
|
||||
|
||||
npart = int(sys.argv[1])
|
||||
dest = sys.argv[2]
|
||||
srcs = sys.argv[3:]
|
||||
|
||||
srcs_sorted = sorted(srcs, key=float)
|
||||
|
||||
processWfiles_sameKs(srcs_sorted, dest, f='d', nparticles=npart)
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import math
|
||||
from qpms.argproc import ArgParser
|
||||
from qpms.argproc import ArgParser, annotate_pdf_metadata
|
||||
|
||||
ap = ArgParser(['rectlattice2d', 'single_particle', 'single_lMax'])
|
||||
ap = ArgParser(['rectlattice2d', 'const_real_background', 'single_particle', 'single_lMax']) # 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)
|
||||
|
@ -116,7 +116,12 @@ res['refractive_index_internal'] = [emg(om).n for om in res['eigval']]
|
|||
#del res['omega'] If contour points are not needed...
|
||||
#del res['ImTW'] # not if dbg=false anyway
|
||||
outfile = defaultprefix + ".npz" if a.output is None else a.output
|
||||
np.savez(outfile, meta=vars(a), empty_freqs=np.array(empty_freqs), **res)
|
||||
np.savez(outfile, meta={**vars(a), 'qpms_version' : qpms.__version__()}, empty_freqs=np.array(empty_freqs),
|
||||
ss_positions=ss.positions, ss_fullvec_poffsets=ss.fullvec_poffsets,
|
||||
ss_fullvec_psizes=ss.fullvec_psizes,
|
||||
ss_bspecs_flat = np.concatenate(ss.bspecs),
|
||||
ss_lattice_basis=ss.lattice_basis, ss_reciprocal_basis = ss.reciprocal_basis,
|
||||
**res)
|
||||
logging.info("Saved to %s" % outfile)
|
||||
|
||||
|
||||
|
@ -128,6 +133,7 @@ if a.plot or (a.plot_out is not None):
|
|||
import matplotlib
|
||||
matplotlib.use('pdf')
|
||||
from matplotlib import pyplot as plt
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(111,)
|
||||
|
@ -151,8 +157,11 @@ if a.plot or (a.plot_out is not None):
|
|||
ax.set_ylim([ymin-.1*yspan, ymax+.1*yspan])
|
||||
ax.set_xlabel('$\hbar \Re \omega / \mathrm{eV}$')
|
||||
ax.set_ylabel('$\hbar \Im \omega / \mathrm{meV}$')
|
||||
|
||||
plotfile = defaultprefix + ".pdf" if a.plot_out is None else a.plot_out
|
||||
fig.savefig(plotfile)
|
||||
with PdfPages(plotfile) as pdf:
|
||||
pdf.savefig(fig)
|
||||
annotate_pdf_metadata(pdf, scriptname="rectlat_simple_modes.py")
|
||||
|
||||
exit(0)
|
||||
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
'''INCOMPLETE! This will read read the refractiveindex.info yaml files
|
||||
and transforms the database into a C source.'''
|
||||
|
||||
import re
|
||||
import os
|
||||
try:
|
||||
from yaml import CLoader as Loader, CDumper as Dumper
|
||||
except ImportError:
|
||||
from yaml import Loader, Dumper
|
||||
|
||||
# Right now, we can process only the 'tabulated nk' data
|
||||
searchfor = '- type: tabulated nk'
|
||||
searchfor = re.compile(searchfor)
|
||||
|
||||
ridatadir = "/u/46/necadam1/unix/repo/refractiveindex.info-database/database/data"
|
||||
|
||||
nktables = dict()
|
||||
|
||||
def find_files_by_pattern (pattern, dir):
|
||||
r = re.compile(pattern)
|
||||
for parent, dnames, fnames in os.walk(ridatadir):
|
||||
for fname in fnames:
|
||||
filename = os.path.join(parent, fname)
|
||||
if os.path.isfile(filename):
|
||||
with open(filename) as f:
|
||||
text = f.read()
|
||||
if r.search(text):
|
||||
yield (
|
||||
|
||||
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
ricbessel # ricatti-bessel psi
|
||||
richankes # ricatti-hankel xi
|
||||
cricbessel
|
||||
crichankel # (same with complex argument)
|
||||
cspherebessel # spherical Bessel jn(z), yn(z)
|
||||
vcfunc # vector coupling coefficients C(m,n|k,l|m+k,w), w = |n-l|,...n+l
|
||||
normalizedlegendre # normalized asssociated legendre functions
|
||||
rotcoef # Generalized spherical functions
|
||||
taufunc # vector spherical harmonics, normalized
|
||||
pifunc # vector spherical harmonics, ?
|
||||
planewavecoef # regular vswf expansion coefficients for a plane wave
|
||||
gaussianbeamcoef # regular vsfw expansion for a gaussian beam
|
||||
sphereplanewavecoef # plane wave expansion coefficients at sphere origins
|
||||
axialtrancoefrecurrence # axial translation ceifficients
|
||||
axialtrancoefinit
|
||||
tranordertest # test to determine convergence of regular vswf addition theorem
|
||||
atcadd
|
||||
atcdim
|
||||
moffset
|
||||
gentrancoef # calculates the vwh translation coefficients for a general translation from one origin to another
|
||||
cartosphere # cartesian to spherical coorsinates
|
||||
eulerrotation # euler rotation of a point specified in cartesian coords
|
||||
ephicoef
|
||||
planewavetruncationorder # test to determine max order of vswf expansion of a plane wave at distance r
|
||||
vwhcalc # calculates the cartesian components of the vswf at position rpos
|
||||
vwhaxialcalc # svwf calculation for an axial translation
|
||||
twobytwoinverse # inverse of a 2x2 matrix
|
||||
transfer
|
||||
|
||||
mpisetup
|
||||
|
||||
module spheredata (lots of declarations!, read all the shit)
|
||||
(...)
|
||||
|
||||
module miecoefdata
|
||||
miecoefcalc # calculation of the max order of sphere expansions and storage of mie coefficients
|
||||
readtmatrix # reads and stores a PARTICLE T matrix
|
||||
lrmodetran # transformation between lr and te tm basis
|
||||
mieoa # optically aptive lorenz/mie coefficients
|
||||
getmiedataall # retrieve the array of mie data
|
||||
getmiedataone # retrieve mie data for a single sphere
|
||||
onemiecoeffmult # multiplies coefficients for sphere i by appropriate lm coefficient
|
||||
multmiecoeffmult # generalized mie coefficient mult
|
||||
dotproduct # vectorproduct for each rhs element of coefficient array
|
||||
|
||||
module translation
|
||||
hostconfiguration # calculates lists for identifying host and interior sphere
|
||||
rottranmtrxsetup # sets up the stored translation matrices and sets other constants
|
||||
rottranmtrxclear # clear the stored translation matrices
|
||||
sphereinteraction # the general sphere interaction driver
|
||||
external_to_external_expansion # outgoing translation operator: a(i) = H(i-j) a(j)
|
||||
external_to_internal_expansion #
|
||||
m1_to_the_n # sign flipped for odd degrees
|
||||
rottranfarfield # far field formula for outgoing vswf translation
|
||||
farfieldtranslationerror # correction ter for hybrid bcgm solution
|
||||
rottran # the vectorized rotation translation-rotation operation !!!!
|
||||
spheregaussianbeamcoef # GB coefficients for sphere-centered expansion, obtained via translation
|
||||
rotvec # rotation of expansion coefficients amn by euler angles
|
||||
|
||||
module scatprops
|
||||
tranorders # determinaniot of maximum orders for target-based expansions
|
||||
amncommonorigin # translation of sphere-based expansions to common target origin
|
||||
lrsphereqeff # general efficiency factor calculation
|
||||
qefficiencyfactors # calling routine for efficiency calculation
|
||||
scatteringmatrix # scattering amplitude sa and matrix sm calculation
|
||||
s11expansion
|
||||
fosmcalc # azimuth-averaged scattering matrix
|
||||
formexpansion # determine the generalized sf expansion for the azimuth-averaged scatt. matrix
|
||||
ranorientscatmatrix
|
||||
ranorientscatmatrixcalc
|
||||
|
||||
module nearfield
|
||||
packcoefficient
|
||||
unpackcoefficient
|
||||
nearfieldspherepart # the field at point xg generated by the spheres
|
||||
nearfieldincidentpart # the incident field at point xg using a regular vswh expansion
|
||||
nearfieldincidentcoef # reshaped array of incident field coefficients
|
||||
nearfieldpointcalc # !
|
||||
nearfieldgridcalc
|
||||
|
||||
module solver
|
||||
tmatrixsoln # calculation of T-mat. via solution of interaction eqs for a generalized plane wave expansion
|
||||
fixedorsoln # solution of interaction exuations for a fixed orientation
|
||||
cbicgff # hybrid bcgm, using far field translation
|
||||
cbicg # bcgm iteration solver
|
|
@ -1,11 +0,0 @@
|
|||
f = 'out'
|
||||
fc = 'outcs'
|
||||
do for [t=3:137] {
|
||||
y = ((t-3) % 45)/3
|
||||
typ = (t-3) % 3
|
||||
n = floor(sqrt(y+1))
|
||||
m = y - (n*(n+1)-1)
|
||||
print 'n = ', n, ', m = ', m, ', typ ', typ
|
||||
plot f using 1:t w linespoints, fc using 1:t w linespoints
|
||||
pause -1
|
||||
}
|
|
@ -0,0 +1,461 @@
|
|||
#LyX 2.4 created this file. For more info see https://www.lyx.org/
|
||||
\lyxformat 584
|
||||
\begin_document
|
||||
\begin_header
|
||||
\save_transient_properties true
|
||||
\origin unavailable
|
||||
\textclass article
|
||||
\use_default_options true
|
||||
\maintain_unincluded_children false
|
||||
\language finnish
|
||||
\language_package default
|
||||
\inputencoding utf8
|
||||
\fontencoding auto
|
||||
\font_roman "default" "default"
|
||||
\font_sans "default" "default"
|
||||
\font_typewriter "default" "default"
|
||||
\font_math "auto" "auto"
|
||||
\font_default_family default
|
||||
\use_non_tex_fonts false
|
||||
\font_sc false
|
||||
\font_roman_osf false
|
||||
\font_sans_osf false
|
||||
\font_typewriter_osf false
|
||||
\font_sf_scale 100 100
|
||||
\font_tt_scale 100 100
|
||||
\use_microtype false
|
||||
\use_dash_ligatures true
|
||||
\graphics default
|
||||
\default_output_format default
|
||||
\output_sync 0
|
||||
\bibtex_command default
|
||||
\index_command default
|
||||
\paperfontsize default
|
||||
\use_hyperref false
|
||||
\papersize default
|
||||
\use_geometry false
|
||||
\use_package amsmath 1
|
||||
\use_package amssymb 1
|
||||
\use_package cancel 1
|
||||
\use_package esint 1
|
||||
\use_package mathdots 1
|
||||
\use_package mathtools 1
|
||||
\use_package mhchem 1
|
||||
\use_package stackrel 1
|
||||
\use_package stmaryrd 1
|
||||
\use_package undertilde 1
|
||||
\cite_engine basic
|
||||
\cite_engine_type default
|
||||
\use_bibtopic false
|
||||
\use_indices false
|
||||
\paperorientation portrait
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 1
|
||||
\use_minted 0
|
||||
\use_lineno 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
\end_index
|
||||
\secnumdepth 3
|
||||
\tocdepth 3
|
||||
\paragraph_separation indent
|
||||
\paragraph_indentation default
|
||||
\is_math_indent 0
|
||||
\math_numbering_side default
|
||||
\quotes_style english
|
||||
\dynamic_quotes 0
|
||||
\papercolumns 1
|
||||
\papersides 1
|
||||
\paperpagestyle default
|
||||
\tablestyle default
|
||||
\tracking_changes false
|
||||
\output_changes false
|
||||
\html_math_output 0
|
||||
\html_css_as_file 0
|
||||
\html_be_strict false
|
||||
\end_header
|
||||
|
||||
\begin_body
|
||||
|
||||
\begin_layout Title
|
||||
Periodic Green's functions vs.
|
||||
VSWF lattice sums
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ud}{\mathrm{d}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\abs}[1]{\left|#1\right|}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\vect}[1]{\mathbf{#1}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\uvec}[1]{\hat{\mathbf{#1}}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\lang english
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ush}[2]{Y_{#1}^{#2}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ushD}[2]{Y'_{#1}^{#2}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\vsh}{\vect A}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\vshD}{\vect{A'}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wfkc}{\vect y}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wfkcout}{\vect u}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wfkcreg}{\vect v}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wckcreg}{a}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wckcout}{f}
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Section
|
||||
Some definitions and useful relations
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\mathcal{H}_{l}^{m}\left(\vect d\right)\equiv h_{l}^{+}\left(\left|\vect d\right|\right)\ush lm\left(\uvec d\right)
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\mathcal{J}_{l}^{m}\left(\vect d\right)\equiv j_{l}\left(\left|\vect d\right|\right)\ush lm\left(\uvec d\right)
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Dual spherical harmonics and waves
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\int\ush lm\ushD{l'}{m'}\,\ud\Omega=\delta_{l,l'}\delta_{m,m'}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\mathcal{J}'_{l}^{m}\left(\vect d\right)\equiv j_{l}\left(\left|\vect d\right|\right)\ushD lm\left(\uvec d\right)
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Expansion of plane wave (CHECKME whether this is really convention-independent,
|
||||
but it seems so)
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
e^{i\kappa\vect r\cdot\uvec r'}=4\pi\sum_{l,m}i^{n}\mathcal{J}'_{l}^{m}\left(\kappa\vect r\right)\ush lm\left(\uvec r'\right)=4\pi\sum_{l,m}i^{n}\mathcal{J}{}_{l}^{m}\left(\kappa\vect r\right)\ushD lm\left(\uvec r'\right)
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
This one should also be convention independent (similarly for
|
||||
\begin_inset Formula $\mathcal{H}_{l}^{m}$
|
||||
\end_inset
|
||||
|
||||
):
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\mathcal{J}_{l}^{m}\left(-\vect r\right)=\left(-1\right)^{l}\mathcal{J}_{l}^{m}\left(\vect r\right).
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Section
|
||||
Helmholtz equation and Green's functions (in 3D)
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Note that the notation does not follow Linton's (where the wavenumbers are
|
||||
often implicit)
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\left(\nabla^{2}+\kappa^{2}\right)G^{(\kappa)}\left(\vect x,\vect x_{0}\right)=\delta\left(\vect x-\vect x_{0}\right)
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
G_{0}^{(\kappa)}\left(\vect x,\vect x_{0}\right) & =G_{0}^{(\kappa)}\left(\vect x-\vect x_{0}\right)=-\frac{\cos\left(\kappa\left|\vect x-\vect x_{0}\right|\right)}{4\pi\left|\vect x-\vect x_{0}\right|}\\
|
||||
G_{\pm}^{(\kappa)}\left(\vect x,\vect x_{0}\right) & =G_{\pm}^{(\kappa)}\left(\vect x-\vect x_{0}\right)=-\frac{e^{\pm i\kappa\left|\vect x-\vect x_{0}\right|}}{4\pi\left|\vect x-\vect x_{0}\right|}=-\frac{i\kappa}{4\pi}h_{0}^{\pm}\left(\kappa\left|\vect x-\vect x_{0}\right|\right)=-\frac{i\kappa}{\sqrt{4\pi}}\mathcal{H}_{0}^{0}\left(\kappa\left|\vect x-\vect x_{0}\right|\right)
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Marginal
|
||||
status open
|
||||
|
||||
\begin_layout Plain Layout
|
||||
\begin_inset Formula $G_{\pm}^{(\kappa)}\left(\vect x,\vect x_{0}\right)=-\frac{i\kappa}{\ush 00}\mathcal{H}_{0}^{0}\left(\kappa\left|\vect x-\vect x_{0}\right|\right)$
|
||||
\end_inset
|
||||
|
||||
in case wacky conventions.
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
Lattice GF [Linton (2.3)]:
|
||||
\begin_inset Formula
|
||||
\begin{equation}
|
||||
G_{\Lambda}^{(\kappa)}\left(\vect s,\vect k\right)\equiv\sum_{\vect R\in\Lambda}G_{+}^{\kappa}\left(\vect s-\vect R\right)e^{i\vect k\cdot\vect R}\label{eq:Lattice GF}
|
||||
\end{equation}
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Section
|
||||
GF expansion and lattice sum definition
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Let's define
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\sigma_{l}^{m}\left(\vect s,\vect k\right)=\sum_{\vect R\in\Lambda}\mathcal{H}_{l}^{m}\left(\kappa\left(\vect s+\vect R\right)\right)e^{i\vect k\cdot\vect R},
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
and also its dual version
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\sigma'_{l}^{m}\left(\vect s,\vect k\right)=\sum_{\vect R\in\Lambda}\mathcal{H}'_{l}^{m}\left(\kappa\left(\vect s+\vect R\right)\right)e^{i\vect k\cdot\vect R}.
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Inspired by [Linton (4.1)]; assuming that
|
||||
\begin_inset Formula $\vect s\notin\Lambda$
|
||||
\end_inset
|
||||
|
||||
, let's expand the lattice Green's function around
|
||||
\begin_inset Formula $\vect s$
|
||||
\end_inset
|
||||
|
||||
:
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{(\kappa)}\left(\vect s+\vect r,\vect k\right)=-i\kappa\sum_{l,m}\tau_{l}^{m}\left(\vect s,\vect k\right)\mathcal{J}_{l}^{m}\left(\kappa\vect r\right)
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
and multiply with a dual SH + integrate
|
||||
\begin_inset Formula
|
||||
\begin{align}
|
||||
\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(\kappa)}\left(\vect s+\vect r,\vect k\right)\ushD{l'}{m'}\left(\uvec r\right) & =-i\kappa\sum_{l,m}\tau_{l}^{m}\left(\vect s,\vect k\right)j_{l}\left(\kappa\left|\vect r\right|\right)\delta_{ll'}\delta_{mm'}\nonumber \\
|
||||
& =-i\kappa\tau_{l'}^{m'}\left(\vect s,\vect k\right)j_{l'}\left(\kappa\left|\vect r\right|\right)\label{eq:tau extraction}
|
||||
\end{align}
|
||||
|
||||
\end_inset
|
||||
|
||||
The expansion coefficients
|
||||
\begin_inset Formula $\tau_{l}^{m}\left(\vect s,\vect k\right)$
|
||||
\end_inset
|
||||
|
||||
is then typically extracted by taking the limit
|
||||
\begin_inset Formula $\left|\vect r\right|\to0$
|
||||
\end_inset
|
||||
|
||||
.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
The relation between
|
||||
\begin_inset Formula $\sigma_{l}^{m}\left(\vect s,\vect k\right)$
|
||||
\end_inset
|
||||
|
||||
and
|
||||
\begin_inset Formula $\tau_{l}^{m}\left(\vect s,\vect k\right)$
|
||||
\end_inset
|
||||
|
||||
can be obtained e.g.
|
||||
from the addition theorem for scalar spherical wavefunctions [Linton (C.3)],
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\mathcal{H}_{l}^{m}\left(\vect a+\vect b\right)=\sum_{l'm'}S_{ll'}^{mm'}\left(\vect b\right)\mathcal{J}_{l'}^{m'}\left(\vect a\right),\quad\left|\vect a\right|<\left|\vect b\right|
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
where for the zeroth degree and order one has [Linton (C.3)]
|
||||
\begin_inset Formula
|
||||
\[
|
||||
S_{0l'}^{0m'}\left(\vect b\right)=\sqrt{4\pi}\mathcal{H}'_{l'}^{m'}\left(-\vect b\right)
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Marginal
|
||||
status open
|
||||
|
||||
\begin_layout Plain Layout
|
||||
In a totally convention-independent version probably looks like
|
||||
\begin_inset Formula $S_{0l'}^{0m'}\left(\vect b\right)=\ush 00\mathcal{H}'_{l'}^{m'}\left(-\vect b\right)$
|
||||
\end_inset
|
||||
|
||||
, but the
|
||||
\begin_inset Formula $Y_{0}^{0}$
|
||||
\end_inset
|
||||
|
||||
will cancel with the expression for GF anyways, so no harm to the final
|
||||
result.
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
From the lattice GF definition
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand eqref
|
||||
reference "eq:Lattice GF"
|
||||
plural "false"
|
||||
caps "false"
|
||||
noprefix "false"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
G_{\Lambda}^{(\kappa)}\left(\vect s+\vect r,\vect k\right) & \equiv\frac{-i\kappa}{\sqrt{4\pi}}\sum_{\vect R\in\Lambda}\mathcal{H}_{0}^{0}\left(\kappa\left(\vect s+\vect r-\vect R\right)\right)e^{i\vect k\cdot\vect R}\\
|
||||
& =\frac{-i\kappa}{\sqrt{4\pi}}\sum_{\vect R\in\Lambda}\mathcal{H}_{0}^{0}\left(\kappa\left(\vect s+\vect r-\vect R\right)\right)e^{i\vect k\cdot\vect R}\\
|
||||
& =\frac{-i\kappa}{\sqrt{4\pi}}\sum_{\vect R\in\Lambda}\sum_{l'm'}S_{0l'}^{0m'}\left(\kappa\left(\vect s-\vect R\right)\right)\mathcal{J}_{l'}^{m'}\left(\kappa\vect r\right)e^{i\vect k\cdot\vect R}\\
|
||||
& =-i\kappa\sum_{\vect R\in\Lambda}\sum_{lm}\mathcal{H}'_{l}^{m}\left(-\kappa\left(\vect s-\vect R\right)\right)\mathcal{J}_{l}^{m}\left(\kappa\vect r\right)e^{i\vect k\cdot\vect R}
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
and mutliplying with dual SH and integrating
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(\kappa)}\left(\vect s+\vect r,\vect k\right)\ushD{l'}{m'}\left(\uvec r\right) & =-i\kappa\sum_{\vect R\in\Lambda}\sum_{lm}\mathcal{H}'_{l}^{m}\left(-\kappa\left(\vect s-\vect R\right)\right)j_{l}\left(\kappa\left|\vect r\right|\right)\delta_{ll'}\delta_{mm'}e^{i\vect k\cdot\vect R}\\
|
||||
& =-i\kappa\sum_{\vect R\in\Lambda}\mathcal{H}'_{l'}^{m'}\left(\kappa\left(-\vect s+\vect R\right)\right)j_{l'}\left(\kappa\left|\vect r\right|\right)e^{i\vect k\cdot\vect R}\\
|
||||
& =-i\kappa\sigma'_{l'}^{m'}\left(-\vect s,\vect k\right)j_{l'}\left(\kappa\left|\vect r\right|\right)
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
and comparing with
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand eqref
|
||||
reference "eq:tau extraction"
|
||||
plural "false"
|
||||
caps "false"
|
||||
noprefix "false"
|
||||
|
||||
\end_inset
|
||||
|
||||
we have
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\tau_{l}^{m}\left(\vect s,\vect k\right)=\sigma'_{l}^{m}\left(-\vect s,\vect k\right).
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Note Note
|
||||
status open
|
||||
|
||||
\begin_layout Plain Layout
|
||||
TODO maybe also define some
|
||||
\begin_inset Formula $\tau'_{l}^{m}$
|
||||
\end_inset
|
||||
|
||||
as expansion coefficients of GF into dual regular SSWFs.
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\end_body
|
||||
\end_document
|
|
@ -0,0 +1,107 @@
|
|||
# Installing QPMS on Android/AOSP (-based) systems
|
||||
|
||||
Yes, it is possible. Basically all you need is a device capable of running [Termux](https://termux.com/) with enough memory to build everything.
|
||||
|
||||
The following instructions have been tested with Termux version 0.118.0 on
|
||||
[e/OS/ R development build on a Samsung Galaxy S10e](https://doc.e.foundation/devices/beyond0lte/install)
|
||||
([e-1.0-r-20220526188878-dev-beyond0lte](https://images.ecloud.global/dev/beyond0lte/)).
|
||||
Presumably, they should work also on stock Android as well, but who
|
||||
in their right mind would run all the spyware by Google & al.?
|
||||
|
||||
Physical keyboard or [remote access](https://wiki.termux.com/wiki/Remote_Access) is strongly recommended. :D
|
||||
|
||||
## Get Termux
|
||||
|
||||
Just [install the Termux app from F-Droid or Github as per instructions](https://github.com/termux/termux-app#f-droid).
|
||||
|
||||
Open Termux; the following steps of these instructions are basically
|
||||
just commands you need to type in Termux.
|
||||
|
||||
## Install prerequisities from termux repositories
|
||||
|
||||
```
|
||||
pkg install python3 cmake git clang build-essential binutils
|
||||
```
|
||||
|
||||
## Build and install GSL
|
||||
|
||||
```
|
||||
curl -O https://www.nic.funet.fi/pub/gnu/ftp.gnu.org/pub/gnu/gsl/gsl-latest.tar.gz
|
||||
tar xf gsl-latest.tar.gz
|
||||
cd gsl-2.7.1
|
||||
./configure --prefix=$PREFIX
|
||||
make # add -j4 or so to make it faster on multicore systems
|
||||
make install
|
||||
cd -
|
||||
```
|
||||
|
||||
## Build and install OpenBLAS
|
||||
|
||||
```
|
||||
git clone https://github.com/xianyi/OpenBLAS.git
|
||||
cd OpenBLAS
|
||||
make
|
||||
make PREFIX=$PREFIX install
|
||||
cd -
|
||||
```
|
||||
|
||||
### Workaround for "broken" setup.py script
|
||||
|
||||
The goal is to fix `setup.py` so that it finds the correct libraries automatically, but in the meantime, you can use this workaround to get the Python part of QPMS installed:
|
||||
|
||||
```
|
||||
ln -s $PREFIX/lib/libopenblas.so $PREFIX/LIB/liblapacke.so
|
||||
```
|
||||
|
||||
## Build and install Numpy
|
||||
|
||||
(Successful build requires the `MATHLIB` environmental variable set, otherwise linking will fail; see https://wiki.termux.com/wiki/Python.)
|
||||
|
||||
```
|
||||
MATHLIB=m pip3 install numpy
|
||||
```
|
||||
|
||||
### Install Sympy
|
||||
|
||||
```
|
||||
pip3 install sympy
|
||||
```
|
||||
|
||||
## Build and install QPMS
|
||||
|
||||
```
|
||||
git clone https://repo.or.cz/qpms.git
|
||||
cd qpms
|
||||
cmake -DCMAKE_INSTALL_PREFIX=$PREFIX . # ugly, TODO make a separate build tree!
|
||||
make install
|
||||
|
||||
python3 setup.py install
|
||||
```
|
||||
|
||||
Hopefully, QPMS has installed successfully. At this point, you should be able
|
||||
to import and use QPMS with some exceptions. First, there is some legacy code
|
||||
in the `qpms.qpms_p` module (which is no longer imported automatically with
|
||||
bare `import qpms`). You shouldn't need this unless you are trying to run some
|
||||
historic Jupyter notebooks or other old custom scripts. It contains a scipy
|
||||
dependence, and scipy is hard to get working in Android environment (as
|
||||
it requires a Fortran compiler to build).
|
||||
|
||||
## Install matplotlib
|
||||
|
||||
If you try to run just `pip3 install matplotlib` in Termux, it might likely
|
||||
fail when installing the `pillow` dependency.
|
||||
First, according to [Termux wiki](https://wiki.termux.com/wiki/Python#Python_module_installation_tips_and_tricks),
|
||||
pillow depends on `libpng` and `libjpeg-turbo`, which are fortunately
|
||||
available in Termux packages.
|
||||
Second, pillow instalation requires an additional environment variable
|
||||
`LDFLAGS="-L/system/lib64"` to be set on 64-bit devices.
|
||||
|
||||
Hence:
|
||||
```
|
||||
pkg install libpng libjpeg-turbo
|
||||
export LDFLAGS="-L/system/lib64" # on 64-bit devices
|
||||
pip3 install matplotlib
|
||||
```
|
||||
|
||||
After this step, you should be able to run the command-line scripts
|
||||
from `misc/` directory and examples from `examples/` directory.
|
|
@ -0,0 +1,266 @@
|
|||
#LyX 2.4 created this file. For more info see https://www.lyx.org/
|
||||
\lyxformat 584
|
||||
\begin_document
|
||||
\begin_header
|
||||
\save_transient_properties true
|
||||
\origin unavailable
|
||||
\textclass article
|
||||
\use_default_options true
|
||||
\maintain_unincluded_children false
|
||||
\language finnish
|
||||
\language_package default
|
||||
\inputencoding utf8
|
||||
\fontencoding auto
|
||||
\font_roman "default" "default"
|
||||
\font_sans "default" "default"
|
||||
\font_typewriter "default" "default"
|
||||
\font_math "auto" "auto"
|
||||
\font_default_family default
|
||||
\use_non_tex_fonts false
|
||||
\font_sc false
|
||||
\font_roman_osf false
|
||||
\font_sans_osf false
|
||||
\font_typewriter_osf false
|
||||
\font_sf_scale 100 100
|
||||
\font_tt_scale 100 100
|
||||
\use_microtype false
|
||||
\use_dash_ligatures true
|
||||
\graphics default
|
||||
\default_output_format default
|
||||
\output_sync 0
|
||||
\bibtex_command default
|
||||
\index_command default
|
||||
\paperfontsize default
|
||||
\use_hyperref false
|
||||
\papersize default
|
||||
\use_geometry false
|
||||
\use_package amsmath 1
|
||||
\use_package amssymb 1
|
||||
\use_package cancel 1
|
||||
\use_package esint 1
|
||||
\use_package mathdots 1
|
||||
\use_package mathtools 1
|
||||
\use_package mhchem 1
|
||||
\use_package stackrel 1
|
||||
\use_package stmaryrd 1
|
||||
\use_package undertilde 1
|
||||
\cite_engine basic
|
||||
\cite_engine_type default
|
||||
\use_bibtopic false
|
||||
\use_indices false
|
||||
\paperorientation portrait
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 1
|
||||
\use_minted 0
|
||||
\use_lineno 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
\end_index
|
||||
\secnumdepth 3
|
||||
\tocdepth 3
|
||||
\paragraph_separation indent
|
||||
\paragraph_indentation default
|
||||
\is_math_indent 0
|
||||
\math_numbering_side default
|
||||
\quotes_style english
|
||||
\dynamic_quotes 0
|
||||
\papercolumns 1
|
||||
\papersides 1
|
||||
\paperpagestyle default
|
||||
\tablestyle default
|
||||
\tracking_changes false
|
||||
\output_changes false
|
||||
\html_math_output 0
|
||||
\html_css_as_file 0
|
||||
\html_be_strict false
|
||||
\end_header
|
||||
|
||||
\begin_body
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ud}{\mathrm{d}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\begin{equation}
|
||||
\Delta_{n}(x,z)\equiv\int_{x}^{\infty}t^{-\frac{1}{2}-n}e^{-t+\frac{z^{2}}{4t}}\ud t\label{eq:Delta definition}
|
||||
\end{equation}
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Integration per partes:
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\int t^{-\frac{1}{2}-n}\ud t=\frac{t^{\frac{1}{2}-n}}{\frac{1}{2}-n};
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\frac{\ud}{\ud t}e^{-t+\frac{z^{2}}{4t}}=\left(-1-\frac{z^{2}}{4t^{2}}\right)e^{-t+\frac{z^{2}}{4t}}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
\left(\frac{1}{2}-n\right)\Delta_{n} & =-x^{\frac{1}{2}-n}e^{-x+\frac{z^{2}}{4x}}+\int_{x}^{\infty}t^{\frac{1}{2}-n}e^{-t+\frac{z^{2}}{4t}}\ud t+\frac{z^{2}}{4}\int_{x}^{\infty}t^{\frac{-3}{2}-n}e^{-t+\frac{z^{2}}{4t}}\ud t\\
|
||||
& =-x^{\frac{1}{2}-n}e^{-x+\frac{z^{2}}{4x}}+\Delta_{n-1}+\frac{z^{2}}{4}\Delta_{n+1},
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\begin{equation}
|
||||
\Delta_{n+1}=\frac{4}{z^{2}}\left(\left(\frac{1}{2}-n\right)\Delta_{n}-\Delta_{n-1}+x^{\frac{1}{2}-n}e^{-x+\frac{z^{2}}{4x}}\right).\label{eq:Delta recurrence}
|
||||
\end{equation}
|
||||
|
||||
\end_inset
|
||||
|
||||
There are obviously wrong signs in Kambe II, (A 3.3).
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Eq.
|
||||
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand eqref
|
||||
reference "eq:Delta recurrence"
|
||||
plural "false"
|
||||
caps "false"
|
||||
noprefix "false"
|
||||
|
||||
\end_inset
|
||||
|
||||
is obviously unsuitable for numerical computation when
|
||||
\begin_inset Formula $z$
|
||||
\end_inset
|
||||
|
||||
approaches 0.
|
||||
However, the definition
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand eqref
|
||||
reference "eq:Delta definition"
|
||||
plural "false"
|
||||
caps "false"
|
||||
noprefix "false"
|
||||
|
||||
\end_inset
|
||||
|
||||
suggests that the function should be analytical around
|
||||
\begin_inset Formula $z=0$
|
||||
\end_inset
|
||||
|
||||
.
|
||||
If
|
||||
\begin_inset Formula $z=0$
|
||||
\end_inset
|
||||
|
||||
, one has (by definition of incomplete Г function)
|
||||
\begin_inset Formula
|
||||
\begin{equation}
|
||||
\Delta_{n}(x,0)=\Gamma\left(\frac{1}{2}-n,x\right).\label{eq:Delta:z = 0}
|
||||
\end{equation}
|
||||
|
||||
\end_inset
|
||||
|
||||
For convenience, label
|
||||
\begin_inset Formula $w=z^{2}/4$
|
||||
\end_inset
|
||||
|
||||
and
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\Delta'_{n}\left(x,w\right)\equiv\int_{x}^{\infty}t^{-\frac{1}{2}-n}e^{-t+\frac{w}{t}}\ud t.
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Differentiating by parameter
|
||||
\begin_inset Formula $w$
|
||||
\end_inset
|
||||
|
||||
(which should be fine as long as the integration contour does not go through
|
||||
zero) gives
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\frac{\partial\Delta'_{n}\left(x,w\right)}{\partial w}=\Delta'_{n+1}\left(x,w\right),
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
so by recurrence
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\frac{\partial^{k}}{\partial w^{k}}\Delta'_{n}\left(x,w\right)=\Delta'_{n+k}\left(x,w\right).
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Together with
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand eqref
|
||||
reference "eq:Delta:z = 0"
|
||||
plural "false"
|
||||
caps "false"
|
||||
noprefix "false"
|
||||
|
||||
\end_inset
|
||||
|
||||
, this gives an expansion around
|
||||
\begin_inset Formula $w=0$
|
||||
\end_inset
|
||||
|
||||
:
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\Delta_{n}'\left(x,w\right)=\sum_{k=0}^{\infty}\Gamma\left(\frac{1}{2}-n-k,x\right)\frac{w^{k}}{k!},
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\Delta_{n}\left(x,z\right)=\sum_{k=0}^{\infty}\Gamma\left(\frac{1}{2}-n-k,x\right)\frac{\left(z/2\right)^{2k}}{k!}.
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
The big negative first arguments in incomplete
|
||||
\begin_inset Formula $\Gamma$
|
||||
\end_inset
|
||||
|
||||
functions should be good (at least I think so, CHECKME), as well as the
|
||||
|
||||
\begin_inset Formula $1/k!$
|
||||
\end_inset
|
||||
|
||||
factor (of course).
|
||||
I am not sure what the convergence radius is, but for
|
||||
\begin_inset Formula $\left|z\right|<2$
|
||||
\end_inset
|
||||
|
||||
there seems to be absolutely no problem in using this formula.
|
||||
\end_layout
|
||||
|
||||
\end_body
|
||||
\end_document
|
|
@ -0,0 +1,677 @@
|
|||
#LyX 2.4 created this file. For more info see https://www.lyx.org/
|
||||
\lyxformat 584
|
||||
\begin_document
|
||||
\begin_header
|
||||
\save_transient_properties true
|
||||
\origin unavailable
|
||||
\textclass article
|
||||
\use_default_options true
|
||||
\maintain_unincluded_children false
|
||||
\language finnish
|
||||
\language_package default
|
||||
\inputencoding utf8
|
||||
\fontencoding auto
|
||||
\font_roman "default" "default"
|
||||
\font_sans "default" "default"
|
||||
\font_typewriter "default" "default"
|
||||
\font_math "auto" "auto"
|
||||
\font_default_family default
|
||||
\use_non_tex_fonts false
|
||||
\font_sc false
|
||||
\font_roman_osf false
|
||||
\font_sans_osf false
|
||||
\font_typewriter_osf false
|
||||
\font_sf_scale 100 100
|
||||
\font_tt_scale 100 100
|
||||
\use_microtype false
|
||||
\use_dash_ligatures true
|
||||
\graphics default
|
||||
\default_output_format default
|
||||
\output_sync 0
|
||||
\bibtex_command default
|
||||
\index_command default
|
||||
\float_placement class
|
||||
\float_alignment class
|
||||
\paperfontsize 10
|
||||
\spacing single
|
||||
\use_hyperref false
|
||||
\papersize a4paper
|
||||
\use_geometry true
|
||||
\use_package amsmath 1
|
||||
\use_package amssymb 1
|
||||
\use_package cancel 1
|
||||
\use_package esint 1
|
||||
\use_package mathdots 1
|
||||
\use_package mathtools 1
|
||||
\use_package mhchem 1
|
||||
\use_package stackrel 1
|
||||
\use_package stmaryrd 1
|
||||
\use_package undertilde 1
|
||||
\cite_engine basic
|
||||
\cite_engine_type default
|
||||
\biblio_style plain
|
||||
\use_bibtopic false
|
||||
\use_indices false
|
||||
\paperorientation portrait
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 1
|
||||
\use_minted 0
|
||||
\use_lineno 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
\end_index
|
||||
\leftmargin 2cm
|
||||
\topmargin 2cm
|
||||
\rightmargin 2cm
|
||||
\bottommargin 2cm
|
||||
\secnumdepth 3
|
||||
\tocdepth 3
|
||||
\paragraph_separation indent
|
||||
\paragraph_indentation default
|
||||
\is_math_indent 0
|
||||
\math_numbering_side default
|
||||
\quotes_style english
|
||||
\dynamic_quotes 0
|
||||
\papercolumns 1
|
||||
\papersides 1
|
||||
\paperpagestyle default
|
||||
\tablestyle default
|
||||
\tracking_changes false
|
||||
\output_changes false
|
||||
\html_math_output 0
|
||||
\html_css_as_file 0
|
||||
\html_be_strict false
|
||||
\end_header
|
||||
|
||||
\begin_body
|
||||
|
||||
\begin_layout Title
|
||||
1D and 2D in 3D Ewald sum
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ud}{\mathrm{d}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\abs}[1]{\left|#1\right|}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\vect}[1]{\mathbf{#1}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\uvec}[1]{\hat{\mathbf{#1}}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\lang english
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ush}[2]{Y_{#1}^{#2}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ushD}[2]{Y'_{#1}^{#2}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\vsh}{\vect A}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\vshD}{\vect{A'}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wfkc}{\vect y}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wfkcout}{\vect u}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wfkcreg}{\vect v}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wckcreg}{a}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wckcout}{f}
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Section
|
||||
General formula
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
We need to find the long-range part of the expansion coefficient
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\begin{equation}
|
||||
\tau_{l'}^{m'}\left(\vect s,\vect k\right)=\frac{i}{\kappa j_{l'}\left(\kappa\left|\vect r\right|\right)}\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(\kappa)}\left(\vect s+\vect r,\vect k\right)\ushD{l'}{m'}\left(\uvec r\right).\label{eq:tau extraction formula}
|
||||
\end{equation}
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
We take [Linton, (2.24)] with slightly modified notation
|
||||
\begin_inset Formula $\left(\vect k_{\vect K}\equiv\vect K+\vect k\right)$
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{(1;\kappa)}\left(\vect r\right)=-\frac{1}{2\pi^{d_{c}/2}\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\vect r}\int_{1/\eta}^{\infty e^{i\pi/4}}e^{-\kappa^{2}\gamma^{2}t^{2}/4}e^{-\left|\vect r^{\bot}\right|^{2}/t^{2}}t^{1-d_{c}}\ud t
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
or, evaluated at point
|
||||
\begin_inset Formula $\vect s+\vect r$
|
||||
\end_inset
|
||||
|
||||
instead
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)=-\frac{1}{2\pi^{d_{c}/2}\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\left(\vect s+\vect r\right)}\int_{1/\eta}^{\infty e^{i\pi/4}}e^{-\kappa^{2}\gamma^{2}t^{2}/4}e^{-\left|\vect s^{\bot}+\vect r^{\bot}\right|^{2}/t^{2}}t^{1-d_{c}}\ud t
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
The integral can be by substitutions taken into the form
|
||||
\begin_inset Note Note
|
||||
status open
|
||||
|
||||
\begin_layout Plain Layout
|
||||
|
||||
\lang english
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{\left(1\right)}\left(\vect r\right)=\frac{\pi^{-d_{c}/2}}{2\mathcal{A}}\sum_{\vect K_{m}\in\Lambda^{*}}e^{i\vect K_{m}\cdot\vect r}\int_{1/\eta}^{\infty\exp\left(i\pi/4\right)}e^{-\kappa^{2}\gamma_{m}^{2}\zeta^{2}/4}e^{-\left|\vect r_{\bot}\right|^{2}/\zeta^{2}}\zeta^{1-d_{c}}\ud\zeta
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Try substitution
|
||||
\begin_inset Formula $t=\zeta^{2}$
|
||||
\end_inset
|
||||
|
||||
: then
|
||||
\begin_inset Formula $\ud t=2\zeta\,\ud\zeta$
|
||||
\end_inset
|
||||
|
||||
(
|
||||
\begin_inset Formula $\ud\zeta=\ud t/2t^{1/2}$
|
||||
\end_inset
|
||||
|
||||
) and
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{\left(1\right)}\left(\vect r\right)=\frac{\pi^{-d_{c}/2}}{4\mathcal{A}}\sum_{\vect K_{m}\in\Lambda^{*}}e^{i\vect K_{m}\cdot\vect r}\int_{1/\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\kappa^{2}\gamma_{m}^{2}t/4}e^{-\left|\vect r_{\bot}\right|^{2}/t}t^{\frac{-d_{c}}{2}}\ud t
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Try subst.
|
||||
|
||||
\begin_inset Formula $\tau=k^{2}\gamma_{m}^{2}/4$
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Plain Layout
|
||||
|
||||
\lang english
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{\left(1\right)}\left(\vect r\right)=\frac{\pi^{-d_{c}/2}}{4\mathcal{A}}\sum_{\vect K_{m}\in\Lambda^{*}}e^{i\vect K_{m}\cdot\vect r}\left(\frac{\kappa\gamma_{m}}{2}\right)^{d_{c}}\int_{\kappa^{2}\gamma_{m}^{2}/4\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\tau}e^{-\left|\vect r_{\bot}\right|^{2}\kappa^{2}\gamma_{m}^{2}/4\tau}\tau^{\frac{-d_{c}}{2}}\ud\tau
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)=-\frac{1}{2\pi^{d_{c}/2}\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\left(\vect s+\vect r\right)}\int_{\kappa^{2}\gamma_{m}^{2}/4\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\tau}e^{-\left|\vect s_{\bot}+\vect r_{\bot}\right|^{2}\kappa^{2}\gamma_{m}^{2}/4\tau}\tau^{-\frac{d_{c}}{2}}\ud\tau
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Foot
|
||||
status open
|
||||
|
||||
\begin_layout Plain Layout
|
||||
[Linton, (2.25)] with slightly modified notation:
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{(1;\kappa)}\left(\vect r\right)=-\frac{1}{\sqrt{4\pi}\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\vect r}\sum_{j=0}^{\infty}\frac{\left(-1\right)^{j}\left|\vect r^{\bot}\right|^{2j}}{j!}\left(\frac{\kappa\gamma_{\vect{\vect k_{\vect K}}}}{2}\right)^{2j-1}\Gamma_{j\vect k_{\vect K}}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
We want to express an expansion in a shifted point, so let's substitute
|
||||
|
||||
\begin_inset Formula $\vect r\to\vect s+\vect r$
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)=-\frac{1}{\sqrt{4\pi}\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\left(\vect s+\vect r\right)}\sum_{j=0}^{\infty}\frac{\left(-1\right)^{j}\left|\vect s^{\bot}+\vect r^{\bot}\right|^{2j}}{j!}\left(\frac{\kappa\gamma_{\vect k_{\vect K}}}{2}\right)^{2j-1}\Gamma_{j\vect k_{\vect K}}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
Let's do the integration to get
|
||||
\begin_inset Formula $\tau_{l}^{m}\left(\vect s,\vect k\right)$
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)\ushD{l'}{m'}\left(\uvec r\right)=-\frac{1}{2\pi^{d_{c}/2}\mathcal{A}}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\left(\vect s+\vect r\right)}\int_{\kappa^{2}\gamma_{\vect k_{\vect K}}^{2}/4\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\tau}e^{-\left|\vect s_{\bot}+\vect r_{\bot}\right|^{2}\kappa^{2}\gamma_{\vect k_{\vect K}}^{2}/4\tau}\tau^{-\frac{d_{c}}{2}}\ud\tau
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
The
|
||||
\begin_inset Formula $\vect r$
|
||||
\end_inset
|
||||
|
||||
-dependent plane wave factor can be also written as
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
e^{i\vect k_{\vect K}\cdot\vect r} & =e^{i\left|\vect k_{\vect K}\right|\vect r\cdot\uvec{\vect k_{\vect K}}}=4\pi\sum_{lm}i^{l}\mathcal{J}'_{l}^{m}\left(\left|\vect k_{\vect K}\right|\vect r\right)\ush lm\left(\uvec{\vect k_{\vect K}}\right)\\
|
||||
& =4\pi\sum_{lm}i^{l}j_{l}\left(\left|\vect k_{\vect K}\right|\left|\vect r\right|\right)\ushD lm\left(\uvec{\vect r}\right)\ush lm\left(\uvec{\vect k_{\vect K}}\right)
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Note Note
|
||||
status open
|
||||
|
||||
\begin_layout Plain Layout
|
||||
or the other way around
|
||||
\begin_inset Formula
|
||||
\[
|
||||
e^{i\vect k_{\vect K}\cdot\vect r}=4\pi\sum_{lm}i^{l}j_{l}\left(\left|\vect k_{\vect K}\right|\left|\vect r\right|\right)\ush lm\left(\uvec{\vect r}\right)\ushD lm\left(\uvec{\vect k_{\vect K}}\right)
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
so
|
||||
\begin_inset Formula
|
||||
\begin{multline*}
|
||||
\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)\ushD{l'}{m'}\left(\uvec r\right)=-\frac{1}{2\pi^{d_{c}/2}\mathcal{A}}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\frac{1}{2\pi\mathcal{A}}\times\\
|
||||
\times\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\vect s}\sum_{lm}4\pi i^{l}j_{l}\left(\left|\vect k_{\vect K}\right|\left|\vect r\right|\right)\ushD lm\left(\uvec r\right)\ush lm\left(\uvec{\vect k_{\vect K}}\right)\int_{\kappa^{2}\gamma_{\vect{\vect k_{\vect K}}}^{2}/4\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\tau}e^{-\left|\vect s_{\bot}+\vect r_{\bot}\right|^{2}\kappa^{2}\gamma_{\vect{\vect k_{\vect K}}}^{2}/4\tau}\tau^{-\frac{d_{c}}{2}}\ud\tau
|
||||
\end{multline*}
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
We also have
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
e^{-\left|\vect s_{\bot}+\vect r_{\bot}\right|^{2}\kappa^{2}\gamma_{\vect K}^{2}/4\tau} & =e^{-\left(\left|\vect s_{\bot}\right|^{2}+\left|\vect r_{\bot}\right|^{2}+2\vect r_{\bot}\cdot\vect s_{\bot}\right)\kappa^{2}\gamma_{\vect K}^{2}/4\tau}\\
|
||||
& =e^{-\left|\vect s_{\bot}\right|^{2}\kappa^{2}\gamma_{\vect K}^{2}/4\tau}\sum_{j=0}^{\infty}\frac{1}{j!}\left(-\frac{\left(\left|\vect r_{\bot}\right|^{2}+2\vect r_{\bot}\cdot\vect s_{\bot}\right)\kappa^{2}\gamma_{\vect K}^{2}}{4\tau}\right)^{j},
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
hence
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)\ushD{l'}{m'}\left(\uvec r\right) & =-\frac{1}{2\pi^{d_{c}/2}\mathcal{A}}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\vect s}\sum_{lm}4\pi i^{l}j_{l}\left(\left|\vect k_{\vect K}\right|\left|\vect r\right|\right)\ushD lm\left(\uvec r\right)\ush lm\left(\uvec{\vect k_{\vect K}}\right)\times\\
|
||||
& \quad\times\sum_{j=0}^{\infty}\frac{1}{j!}\left(-\frac{\left(\left|\vect r_{\bot}\right|^{2}+2\vect r_{\bot}\cdot\vect s_{\bot}\right)\kappa^{2}\gamma_{\vect{\vect k_{\vect K}}}^{2}}{4}\right)^{j}\underbrace{\int_{\kappa^{2}\gamma_{\vect K}^{2}/4\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\tau}e^{-\left|\vect s_{\bot}\right|^{2}\kappa^{2}\gamma_{\vect K}^{2}/4\tau}\tau^{-\frac{d_{c}}{2}-j}\ud\tau}_{\Delta_{j}^{\left(d_{\Lambda}\right)}}\\
|
||||
& =-\frac{1}{2\pi^{d_{c}/2}\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\vect s}\sum_{lm}4\pi i^{l}j_{l}\left(\left|\vect k_{\vect K}\right|\left|\vect r\right|\right)\ush lm\left(\uvec{\vect k_{\vect K}}\right)\sum_{j=0}^{\infty}\frac{\Delta_{j}^{\left(d_{\Lambda}\right)}}{j!}\times\\
|
||||
& \quad\times\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left(-\frac{\left(\left|\vect r_{\bot}\right|^{2}+2\vect r_{\bot}\cdot\vect s_{\bot}\right)\kappa^{2}\gamma_{\vect k_{\vect K}}^{2}}{4}\right)^{j}\\
|
||||
& =-\frac{1}{2\pi^{d_{c}/2}\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\vect s}\sum_{lm}4\pi i^{l}j_{l}\left(\left|\vect k_{\vect K}\right|\left|\vect r\right|\right)\ush lm\left(\uvec{\vect k_{\vect K}}\right)\sum_{j=0}^{\infty}\frac{\left(-1\right)^{j}}{j!}\Delta_{j}^{\left(d_{\Lambda}\right)}\times\\
|
||||
& \quad\times\left(\frac{\kappa\gamma_{\vect{\vect k_{\vect K}}}}{2}\right)^{2j}\sum_{k=0}^{j}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left|\vect r_{\bot}\right|^{2(j-k)}\left(2\vect r_{\bot}\cdot\vect s_{\bot}\right)^{k}.
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
If we label
|
||||
\begin_inset Formula $\left|\vect r_{\bot}\right|\left|\vect s_{\bot}\right|\cos\varphi\equiv\vect r_{\bot}\cdot\vect s_{\bot}$
|
||||
\end_inset
|
||||
|
||||
, we have
|
||||
\begin_inset Formula
|
||||
\begin{multline*}
|
||||
\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)\ushD{l'}{m'}\left(\uvec r\right)=-\frac{1}{2\pi^{d_{c}/2}\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\vect s}\sum_{lm}4\pi i^{l}j_{l}\left(\left|\vect k_{\vect K}\right|\left|\vect r\right|\right)\ush lm\left(\uvec{\vect k_{\vect K}}\right)\times\\
|
||||
\times\sum_{j=0}^{\infty}\frac{\left(-1\right)^{j}}{j!}\Delta_{j}^{\left(d_{\Lambda}\right)}\left(\frac{\kappa\gamma_{\vect k_{\vect K}}}{2}\right)^{2j}\sum_{k=0}^{j}\left(2\left|\vect s_{\bot}\right|\right)^{k}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left|\vect r_{\bot}\right|^{2j-k}\left(\cos\varphi\right)^{k}
|
||||
\end{multline*}
|
||||
|
||||
\end_inset
|
||||
|
||||
and if we label
|
||||
\begin_inset Formula $\left|\vect r\right|\sin\vartheta\equiv\left|\vect r_{\bot}\right|$
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\begin{multline*}
|
||||
\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)\ushD{l'}{m'}\left(\uvec r\right)=-\frac{1}{2\pi^{d_{c}/2}\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\vect s}\sum_{lm}4\pi i^{l}j_{l}\left(\left|\vect k_{\vect K}\right|\left|\vect r\right|\right)\ush lm\left(\uvec{\vect k_{\vect K}}\right)\sum_{j=0}^{\infty}\frac{\left(-1\right)^{j}}{j!}\Delta_{j}^{\left(d_{\Lambda}\right)}\left(\frac{\kappa\gamma_{\vect k_{\vect K}}}{2}\right)^{2j}\times\\
|
||||
\times\sum_{k=0}^{j}\left|\vect r\right|^{2j-k}\left(2\left|\vect s_{\bot}\right|\right)^{k}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left(\sin\vartheta\right)^{2j-k}\left(\cos\varphi\right)^{k}.
|
||||
\end{multline*}
|
||||
|
||||
\end_inset
|
||||
|
||||
Now let's put the RHS into
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand eqref
|
||||
reference "eq:tau extraction formula"
|
||||
plural "false"
|
||||
caps "false"
|
||||
noprefix "false"
|
||||
|
||||
\end_inset
|
||||
|
||||
and try eliminating some sum by taking the limit
|
||||
\begin_inset Formula $\left|\vect r\right|\to0$
|
||||
\end_inset
|
||||
|
||||
.
|
||||
We have
|
||||
\begin_inset Formula $j_{l}\left(\left|\vect k_{\vect K}\right|\left|\vect r\right|\right)\sim\left(\left|\vect k_{\vect K}\right|\left|\vect r\right|\right)^{l}/\left(2l+1\right)!!$
|
||||
\end_inset
|
||||
|
||||
; the denominator from
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand eqref
|
||||
reference "eq:tau extraction formula"
|
||||
plural "false"
|
||||
caps "false"
|
||||
noprefix "false"
|
||||
|
||||
\end_inset
|
||||
|
||||
behaves like
|
||||
\begin_inset Formula $j_{l'}\left(\kappa\left|\vect r\right|\right)\sim\left(\kappa\left|\vect r\right|\right)^{l'}/\left(2l'+1\right)!!.$
|
||||
\end_inset
|
||||
|
||||
The leading terms are hence those with
|
||||
\begin_inset Formula $\left|\vect r\right|^{l-l'+2j-k}$
|
||||
\end_inset
|
||||
|
||||
.
|
||||
So
|
||||
\begin_inset Formula
|
||||
\begin{multline*}
|
||||
\tau_{l'}^{m'}\left(\vect s,\vect k\right)=\frac{-i}{2\pi^{d_{c}/2}\mathcal{A}\kappa^{1+l'}}\left(2l'+1\right)!!\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\vect s}\sum_{lm}4\pi i^{l}\frac{\left|\vect k_{\vect K}\right|^{l}}{\left(2l+1\right)!!}\ush lm\left(\uvec{\vect k_{\vect K}}\right)\times\\
|
||||
\times\sum_{j=0}^{\infty}\frac{\left(-1\right)^{j}}{j!}\Delta_{j}^{\left(d_{\Lambda}\right)}\left(\frac{\kappa\gamma_{\vect k_{\vect K}}}{2}\right)^{2j}\sum_{k=0}^{j}\delta_{l'-l,2j-k}\left(2\left|\vect s_{\bot}\right|\right)^{k}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left(\sin\vartheta\right)^{l'-l}\left(\cos\varphi\right)^{k}.
|
||||
\end{multline*}
|
||||
|
||||
\end_inset
|
||||
|
||||
Let's now focus on rearranging the sums; we have
|
||||
\begin_inset Formula
|
||||
\[
|
||||
S(l')\equiv\sum_{l=0}^{\infty}\sum_{j=0}^{\infty}\sum_{k=0}^{j}\delta_{l'-l,2j-k}f(l',l,j,k)=\sum_{l=0}^{\infty}\sum_{j=0}^{\infty}\sum_{k=0}^{j}\delta_{l'-l,2j-k}f(l',l,j,2j-l'+l)
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
We have
|
||||
\begin_inset Formula $0\le k\le j$
|
||||
\end_inset
|
||||
|
||||
, hence
|
||||
\begin_inset Formula $0\le2j-l'+l\le j$
|
||||
\end_inset
|
||||
|
||||
, hence
|
||||
\begin_inset Formula $-2j\le-l'+l\le-j$
|
||||
\end_inset
|
||||
|
||||
, hence also
|
||||
\begin_inset Formula $l'-2j\le l\le l'-j$
|
||||
\end_inset
|
||||
|
||||
, which gives the opportunity to swap the
|
||||
\begin_inset Formula $l,j$
|
||||
\end_inset
|
||||
|
||||
sums and the
|
||||
\begin_inset Formula $l$
|
||||
\end_inset
|
||||
|
||||
-sum becomes finite; so also consuming
|
||||
\begin_inset Formula $\sum_{k=0}^{j}\delta_{l'-l,2j-k}$
|
||||
\end_inset
|
||||
|
||||
we get
|
||||
\begin_inset Formula
|
||||
\[
|
||||
S(l')=\sum_{j=0}^{\infty}\sum_{l=\max(0,l'-2j)}^{l'-j}f(l',l,j,2j-l'+l).
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Finally, we see that the interval of valid
|
||||
\begin_inset Formula $l$
|
||||
\end_inset
|
||||
|
||||
becomes empty when
|
||||
\begin_inset Formula $l'-j<0$
|
||||
\end_inset
|
||||
|
||||
, i.e.
|
||||
|
||||
\begin_inset Formula $j>l'$
|
||||
\end_inset
|
||||
|
||||
; so we get a finite sum
|
||||
\begin_inset Formula
|
||||
\[
|
||||
S(l')=\sum_{j=0}^{l'}\sum_{l=\max(0,l'-2j)}^{l'-j}f(l',l,j,2j-l'+l).
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Applying rearrangement,
|
||||
\begin_inset Formula
|
||||
\begin{multline*}
|
||||
\tau_{l'}^{m'}\left(\vect s,\vect k\right)=\frac{-i}{2\pi^{d_{c}/2}\mathcal{A}\kappa}\frac{\left(2l'+1\right)!!}{\kappa^{l'}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\vect s}\sum_{j=0}^{l'}\frac{\left(-1\right)^{j}}{j!}\Delta_{j}^{\left(d_{\Lambda}\right)}\left(\frac{\kappa\gamma_{\vect k_{\vect K}}}{2}\right)^{2j}\times\sum_{l=\max\left(0,l'-2j\right)}^{l'-j}4\pi i^{l}\left(2\left|\vect s_{\bot}\right|\right)^{2j-l'+l}\frac{\left|\vect k_{\vect K}\right|^{l}}{\left(2l+1\right)!!}\\
|
||||
\times\sum_{m=-l}^{l}\ush lm\left(\uvec{\vect k_{\vect K}}\right)\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left(\sin\vartheta\right)^{l'-l}\left(\cos\varphi\right)^{2j-l'+l},
|
||||
\end{multline*}
|
||||
|
||||
\end_inset
|
||||
|
||||
or replacing the angles with their original definition,
|
||||
\begin_inset Formula
|
||||
\begin{multline*}
|
||||
\tau_{l'}^{m'}\left(\vect s,\vect k\right)=\frac{-i}{2\pi^{d_{c}/2}\mathcal{A}\kappa}\frac{\left(2l'+1\right)!!}{\kappa^{l'}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\vect s}\sum_{j=0}^{l'}\frac{\left(-1\right)^{j}}{j!}\Delta_{j}^{\left(d_{\Lambda}\right)}\left(\frac{\kappa\gamma_{\vect K}}{2}\right)^{2j}\times\sum_{l=\max\left(0,l'-2j\right)}^{l'-j}4\pi i^{l}\left(2\left|\vect s_{\bot}\right|\right)^{2j-l'+l}\frac{\left|\vect k_{\vect K}\right|^{l}}{\left(2l+1\right)!!}\\
|
||||
\times\sum_{m=-l}^{l}\ush lm\left(\uvec K\right)\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left(\frac{\left|\vect r_{\bot}\right|}{\left|\vect r\right|}\right)^{l'-l}\left(\frac{\vect r_{\bot}\cdot\vect s_{\bot}}{\left|\vect r_{\bot}\right|\left|\vect s_{\bot}\right|}\right)^{2j-l'+l},
|
||||
\end{multline*}
|
||||
|
||||
\end_inset
|
||||
|
||||
and if we want a
|
||||
\begin_inset Formula $\sigma_{l'}^{m'}\left(\vect s,\vect k\right)$
|
||||
\end_inset
|
||||
|
||||
instead, we reverse the sign of
|
||||
\begin_inset Formula $\vect s$
|
||||
\end_inset
|
||||
|
||||
and replace all spherical harmonics with their dual counterparts:
|
||||
\begin_inset Formula
|
||||
\begin{multline*}
|
||||
\sigma_{l'}^{m'}\left(\vect s,\vect k\right)=\frac{-i}{2\pi^{d_{c}/2}\mathcal{A}\kappa}\frac{\left(2l'+1\right)!!}{\kappa^{l'}}\sum_{\vect K\in\Lambda^{*}}e^{-i\vect k_{\vect K}\cdot\vect s}\sum_{j=0}^{l'}\frac{\left(-1\right)^{j}}{j!}\Delta_{j}^{\left(d_{\Lambda}\right)}\left(\frac{\kappa\gamma_{\vect k_{\vect K}}}{2}\right)^{2j}\sum_{l=\max\left(0,l'-2j\right)}^{l'-j}4\pi i^{l}\left(2\left|\vect s_{\bot}\right|\right)^{2j-l'+l}\frac{\left|\vect k_{\vect K}\right|^{l}}{\left(2l+1\right)!!}\times\\
|
||||
\times\sum_{m=-l}^{l}\ushD lm\left(\uvec{\vect k_{\vect K}}\right)\int\ud\Omega_{\vect r}\,\ush{l'}{m'}\left(\uvec r\right)\ush lm\left(\uvec r\right)\left(\frac{\left|\vect r_{\bot}\right|}{\left|\vect r\right|}\right)^{l'-l}\left(\frac{-\vect r_{\bot}\cdot\vect s_{\bot}}{\left|\vect r_{\bot}\right|\left|\vect s_{\bot}\right|}\right)^{2j-l'+l},
|
||||
\end{multline*}
|
||||
|
||||
\end_inset
|
||||
|
||||
and remembering that in the plane wave expansion the
|
||||
\begin_inset Quotes eld
|
||||
\end_inset
|
||||
|
||||
duality
|
||||
\begin_inset Quotes erd
|
||||
\end_inset
|
||||
|
||||
is interchangeable,
|
||||
\begin_inset Formula
|
||||
\begin{multline*}
|
||||
\sigma_{l'}^{m'}\left(\vect s,\vect k\right)=\frac{-i}{2\pi^{d_{c}/2}\mathcal{A}\kappa}\frac{\left(2l'+1\right)!!}{\kappa^{l'}}\sum_{\vect K\in\Lambda^{*}}e^{-i\vect k_{\vect K}\cdot\vect s}\sum_{j=0}^{l'}\frac{\left(-1\right)^{j}}{j!}\Delta_{j}^{\left(d_{\Lambda}\right)}\left(\frac{\kappa\gamma_{\vect k_{\vect K}}}{2}\right)^{2j}\sum_{l=\max\left(0,l'-2j\right)}^{l'-j}4\pi i^{l}\left(2\left|\vect s_{\bot}\right|\right)^{2j-l'+l}\frac{\left|\vect k_{\vect K}\right|^{l}}{\left(2l+1\right)!!}\times\\
|
||||
\times\sum_{m=-l}^{l}\ush lm\left(\uvec{\vect k_{\vect K}}\right)\underbrace{\int\ud\Omega_{\vect r}\,\ush{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left(\frac{\left|\vect r_{\bot}\right|}{\left|\vect r\right|}\right)^{l'-l}\left(\frac{-\vect r_{\bot}\cdot\vect s_{\bot}}{\left|\vect r_{\bot}\right|\left|\vect s_{\bot}\right|}\right)^{2j-l'+l}}_{\equiv A_{l',l,m',m,j}^{\left(d_{\Lambda}\right)}}.
|
||||
\end{multline*}
|
||||
|
||||
\end_inset
|
||||
|
||||
The angular integral is easier to evaluate when
|
||||
\begin_inset Formula $d_{\Lambda}=2$
|
||||
\end_inset
|
||||
|
||||
, because then
|
||||
\begin_inset Formula $\vect r_{\bot}$
|
||||
\end_inset
|
||||
|
||||
is parallel (or antiparallel) to
|
||||
\begin_inset Formula $\vect s_{\bot}$
|
||||
\end_inset
|
||||
|
||||
, which gives
|
||||
\begin_inset Formula
|
||||
\[
|
||||
A_{l',l,m',m,j}^{\left(2\right)}=\left(-\frac{\vect r_{\bot}\cdot\vect s_{\bot}}{\left|\vect r_{\bot}\cdot\vect s_{\bot}\right|}\right)^{2j-l'+l}\int\ud\Omega_{\vect r}\,\ush{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left(\frac{\left|\vect r_{\bot}\right|}{\left|\vect r\right|}\right)^{2j}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
and if we set the normal of the lattice correspond to the
|
||||
\begin_inset Formula $z$
|
||||
\end_inset
|
||||
|
||||
axis, the azimuthal part of the integral will become zero unless
|
||||
\begin_inset Formula $m'=m$
|
||||
\end_inset
|
||||
|
||||
for any meaningful spherical harmonics convention, and the polar part for
|
||||
the only nonzero case has a closed-form expression, see e.g.
|
||||
[Linton (A.15)], so one arrives at an expression similar to [Kambe II, (3.15)]
|
||||
\lang english
|
||||
|
||||
\begin_inset Formula
|
||||
\begin{multline}
|
||||
\sigma_{l,m}^{\left(\mathrm{L},\eta\right)}\left(\vect k,\vect s\right)=-\frac{i^{l+1}}{\kappa^{2}\mathcal{A}}\pi^{3/2}2\left(\left(l-m\right)/2\right)!\left(\left(l+m\right)/2\right)!\times\\
|
||||
\times\sum_{\vect K\in\Lambda^{*}}e^{i\vect k_{\vect K}\cdot\vect s}\ush lm\left(\vect k_{\vect K}\right)\sum_{j=0}^{l-\left|m\right|}\left(-1\right)^{j}\gamma_{\vect k_{\vect K}}^{2}{}^{2j+1}\times\\
|
||||
\times\Delta_{j}\left(\frac{\kappa^{2}\gamma_{\vect k_{\vect K}}^{2}}{4\eta^{2}},-i\kappa\gamma_{\vect k_{\vect K}}^{2}s_{\perp}\right)\times\\
|
||||
\times\sum_{\substack{s\\
|
||||
j\le s\le\min\left(2j,l-\left|m\right|\right)\\
|
||||
l-j+\left|m\right|\,\mathrm{evej}
|
||||
}
|
||||
}\frac{1}{\left(2j-s\right)!\left(s-j\right)!}\frac{\left(-\kappa s_{\perp}\right)^{2j-s}\left(\left|\vect k_{\vect K}\right|/\kappa\right)^{l-s}}{\left(\frac{1}{2}\left(l-m-s\right)\right)!\left(\frac{1}{2}\left(l+m-s\right)\right)!}\label{eq:Ewald in 3D long-range part 1D 2D-1}
|
||||
\end{multline}
|
||||
|
||||
\end_inset
|
||||
|
||||
where
|
||||
\begin_inset Formula $s_{\perp}\equiv\vect s\cdot\uvec z=\vect s_{\bot}\cdot\uvec z$
|
||||
\end_inset
|
||||
|
||||
.
|
||||
If
|
||||
\begin_inset Formula $d_{\Lambda}=1$
|
||||
\end_inset
|
||||
|
||||
, the angular becomes more complicated to evaluate due to the different
|
||||
behaviour of the
|
||||
\begin_inset Formula $\vect r_{\bot}\cdot\vect s_{\bot}/\left|\vect r_{\bot}\right|\left|\vect s_{\bot}\right|$
|
||||
\end_inset
|
||||
|
||||
factor.
|
||||
The choice of coordinates can make most of the terms dissapear: if the
|
||||
lattice is set parallel to the
|
||||
\begin_inset Formula $z$
|
||||
\end_inset
|
||||
|
||||
axis,
|
||||
\begin_inset Formula $A_{l',l,m',m,j}^{\left(1\right)}$
|
||||
\end_inset
|
||||
|
||||
is zero unless
|
||||
\begin_inset Formula $m=0$
|
||||
\end_inset
|
||||
|
||||
, but one still has
|
||||
\begin_inset Formula
|
||||
\[
|
||||
A_{l',l,m',0,j}^{\left(1\right)}=\pi\delta_{m',l'-l-2j}\lambda'_{l0}\lambda_{l'm'}\int_{-1}^{1}\ud x\,P_{l'}^{m'}\left(x\right)P_{l}^{0}\left(x\right)\left(1-x^{2}\right)^{\frac{l'-l}{2}}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
where
|
||||
\begin_inset Formula $\lambda_{lm}$
|
||||
\end_inset
|
||||
|
||||
are constants depending on the conventions for spherical harmonics.
|
||||
This does not seem to have such a nice closed-form expression as in the
|
||||
2D case, but it can be evaluated e.g.
|
||||
using the common recurrence relations for associated Legendre polynomials.
|
||||
Of course when
|
||||
\begin_inset Formula $\vect s=0$
|
||||
\end_inset
|
||||
|
||||
, one gets relatively nice closed expressions, such as those in [Linton].
|
||||
\end_layout
|
||||
|
||||
\end_body
|
||||
\end_document
|
|
@ -0,0 +1,976 @@
|
|||
#LyX 2.4 created this file. For more info see https://www.lyx.org/
|
||||
\lyxformat 584
|
||||
\begin_document
|
||||
\begin_header
|
||||
\save_transient_properties true
|
||||
\origin unavailable
|
||||
\textclass article
|
||||
\use_default_options true
|
||||
\maintain_unincluded_children false
|
||||
\language finnish
|
||||
\language_package default
|
||||
\inputencoding utf8
|
||||
\fontencoding auto
|
||||
\font_roman "default" "default"
|
||||
\font_sans "default" "default"
|
||||
\font_typewriter "default" "default"
|
||||
\font_math "auto" "auto"
|
||||
\font_default_family default
|
||||
\use_non_tex_fonts false
|
||||
\font_sc false
|
||||
\font_roman_osf false
|
||||
\font_sans_osf false
|
||||
\font_typewriter_osf false
|
||||
\font_sf_scale 100 100
|
||||
\font_tt_scale 100 100
|
||||
\use_microtype false
|
||||
\use_dash_ligatures true
|
||||
\graphics default
|
||||
\default_output_format default
|
||||
\output_sync 0
|
||||
\bibtex_command default
|
||||
\index_command default
|
||||
\float_placement class
|
||||
\float_alignment class
|
||||
\paperfontsize default
|
||||
\spacing single
|
||||
\use_hyperref false
|
||||
\papersize a4paper
|
||||
\use_geometry true
|
||||
\use_package amsmath 1
|
||||
\use_package amssymb 1
|
||||
\use_package cancel 1
|
||||
\use_package esint 1
|
||||
\use_package mathdots 1
|
||||
\use_package mathtools 1
|
||||
\use_package mhchem 1
|
||||
\use_package stackrel 1
|
||||
\use_package stmaryrd 1
|
||||
\use_package undertilde 1
|
||||
\cite_engine basic
|
||||
\cite_engine_type default
|
||||
\biblio_style plain
|
||||
\use_bibtopic false
|
||||
\use_indices false
|
||||
\paperorientation portrait
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 1
|
||||
\use_minted 0
|
||||
\use_lineno 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
\end_index
|
||||
\leftmargin 2cm
|
||||
\topmargin 2cm
|
||||
\rightmargin 2cm
|
||||
\bottommargin 2cm
|
||||
\secnumdepth 3
|
||||
\tocdepth 3
|
||||
\paragraph_separation indent
|
||||
\paragraph_indentation default
|
||||
\is_math_indent 0
|
||||
\math_numbering_side default
|
||||
\quotes_style english
|
||||
\dynamic_quotes 0
|
||||
\papercolumns 1
|
||||
\papersides 1
|
||||
\paperpagestyle default
|
||||
\tablestyle default
|
||||
\tracking_changes false
|
||||
\output_changes false
|
||||
\html_math_output 0
|
||||
\html_css_as_file 0
|
||||
\html_be_strict false
|
||||
\end_header
|
||||
|
||||
\begin_body
|
||||
|
||||
\begin_layout Title
|
||||
1D in 3D Ewald sum
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ud}{\mathrm{d}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\abs}[1]{\left|#1\right|}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\vect}[1]{\mathbf{#1}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\uvec}[1]{\hat{\mathbf{#1}}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\lang english
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ush}[2]{Y_{#1}^{#2}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ushD}[2]{Y'_{#1}^{#2}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\vsh}{\vect A}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\vshD}{\vect{A'}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wfkc}{\vect y}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wfkcout}{\vect u}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wfkcreg}{\vect v}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wckcreg}{a}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\wckcout}{f}
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Section
|
||||
General formula
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
We need to find the expansion coefficient
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\begin{equation}
|
||||
\tau_{l'}^{m'}\left(\vect s,\vect k\right)=\frac{i}{\kappa j_{l'}\left(\kappa\left|\vect r\right|\right)}\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(\kappa)}\left(\vect s+\vect r,\vect k\right)\ushD{l'}{m'}\left(\uvec r\right).\label{eq:tau extraction formula}
|
||||
\end{equation}
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
[Linton, (2.24)] with slightly modified notation and setting
|
||||
\begin_inset Formula $d_{c}=2$
|
||||
\end_inset
|
||||
|
||||
:
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{(1;\kappa)}\left(\vect r\right)=-\frac{1}{2\pi\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\vect r}\int_{1/\eta}^{\infty e^{i\pi/4}}e^{-\kappa^{2}\gamma^{2}t^{2}/4}e^{-\left|\vect r^{\bot}\right|^{2}/t^{2}}t^{-1}\ud t
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
or, evaluated at point
|
||||
\begin_inset Formula $\vect s+\vect r$
|
||||
\end_inset
|
||||
|
||||
instead
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)=-\frac{1}{2\pi\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\left(\vect s+\vect r\right)}\int_{1/\eta}^{\infty e^{i\pi/4}}e^{-\kappa^{2}\gamma^{2}t^{2}/4}e^{-\left|\vect s^{\bot}+\vect r^{\bot}\right|^{2}/t^{2}}t^{-1}\ud t
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
The integral can be by substitutions taken into the form
|
||||
\begin_inset Note Note
|
||||
status open
|
||||
|
||||
\begin_layout Plain Layout
|
||||
|
||||
\lang english
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{\left(1\right)}\left(\vect r\right)=\frac{\pi^{-d_{c}/2}}{2\mathcal{A}}\sum_{\vect K_{m}\in\Lambda^{*}}e^{i\vect K_{m}\cdot\vect r}\int_{1/\eta}^{\infty\exp\left(i\pi/4\right)}e^{-\kappa^{2}\gamma_{m}^{2}\zeta^{2}/4}e^{-\left|\vect r_{\bot}\right|^{2}/\zeta^{2}}\zeta^{1-d_{c}}\ud\zeta
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Try substitution
|
||||
\begin_inset Formula $t=\zeta^{2}$
|
||||
\end_inset
|
||||
|
||||
: then
|
||||
\begin_inset Formula $\ud t=2\zeta\,\ud\zeta$
|
||||
\end_inset
|
||||
|
||||
(
|
||||
\begin_inset Formula $\ud\zeta=\ud t/2t^{1/2}$
|
||||
\end_inset
|
||||
|
||||
) and
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{\left(1\right)}\left(\vect r\right)=\frac{\pi^{-d_{c}/2}}{4\mathcal{A}}\sum_{\vect K_{m}\in\Lambda^{*}}e^{i\vect K_{m}\cdot\vect r}\int_{1/\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\kappa^{2}\gamma_{m}^{2}t/4}e^{-\left|\vect r_{\bot}\right|^{2}/t}t^{\frac{-d_{c}}{2}}\ud t
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Try subst.
|
||||
|
||||
\begin_inset Formula $\tau=k^{2}\gamma_{m}^{2}/4$
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Plain Layout
|
||||
|
||||
\lang english
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{\left(1\right)}\left(\vect r\right)=\frac{\pi^{-d_{c}/2}}{4\mathcal{A}}\sum_{\vect K_{m}\in\Lambda^{*}}e^{i\vect K_{m}\cdot\vect r}\left(\frac{\kappa\gamma_{m}}{2}\right)^{d_{c}}\int_{\kappa^{2}\gamma_{m}^{2}/4\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\tau}e^{-\left|\vect r_{\bot}\right|^{2}\kappa^{2}\gamma_{m}^{2}/4\tau}\tau^{\frac{-d_{c}}{2}}\ud\tau
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)=-\frac{1}{2\pi\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\left(\vect s+\vect r\right)}\int_{\kappa^{2}\gamma_{m}^{2}/4\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\tau}e^{-\left|\vect s_{\bot}+\vect r_{\bot}\right|^{2}\kappa^{2}\gamma_{m}^{2}/4\tau}\tau^{-1}\ud\tau
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Foot
|
||||
status open
|
||||
|
||||
\begin_layout Plain Layout
|
||||
[Linton, (2.25)] with slightly modified notation:
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{(1;\kappa)}\left(\vect r\right)=-\frac{1}{\sqrt{4\pi}\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\vect r}\sum_{j=0}^{\infty}\frac{\left(-1\right)^{j}\left|\vect r^{\bot}\right|^{2j}}{j!}\left(\frac{\kappa\gamma_{\vect K}}{2}\right)^{2j-1}\Gamma_{j\vect K}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
We want to express an expansion in a shifted point, so let's substitute
|
||||
|
||||
\begin_inset Formula $\vect r\to\vect s+\vect r$
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)=-\frac{1}{\sqrt{4\pi}\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\left(\vect s+\vect r\right)}\sum_{j=0}^{\infty}\frac{\left(-1\right)^{j}\left|\vect s^{\bot}+\vect r^{\bot}\right|^{2j}}{j!}\left(\frac{\kappa\gamma_{\vect K}}{2}\right)^{2j-1}\Gamma_{j\vect K}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
Let's do the integration to get
|
||||
\begin_inset Formula $\tau_{l}^{m}\left(\vect s,\vect k\right)$
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)\ushD{l'}{m'}\left(\uvec r\right)=-\frac{1}{2\pi\mathcal{A}}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\frac{1}{2\pi\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\left(\vect s+\vect r\right)}\int_{\kappa^{2}\gamma_{\vect K}^{2}/4\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\tau}e^{-\left|\vect s_{\bot}+\vect r_{\bot}\right|^{2}\kappa^{2}\gamma_{\vect K}^{2}/4\tau}\tau^{-1}\ud\tau
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
The
|
||||
\begin_inset Formula $\vect r$
|
||||
\end_inset
|
||||
|
||||
-dependent plane wave factor can be also written as
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
e^{i\vect K\cdot\vect r} & =e^{i\left|\vect K\right|\vect r\cdot\uvec K}=4\pi\sum_{lm}i^{l}\mathcal{J}'_{l}^{m}\left(\left|\vect K\right|\vect r\right)\ush lm\left(\uvec K\right)\\
|
||||
& =4\pi\sum_{lm}i^{l}j_{l}\left(\left|\vect K\right|\left|\vect r\right|\right)\ushD lm\left(\uvec{\vect r}\right)\ush lm\left(\uvec K\right)
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Note Note
|
||||
status open
|
||||
|
||||
\begin_layout Plain Layout
|
||||
or the other way around
|
||||
\begin_inset Formula
|
||||
\[
|
||||
e^{i\vect K\cdot\vect r}=4\pi\sum_{lm}i^{l}j_{l}\left(\left|\vect K\right|\left|\vect r\right|\right)\ush lm\left(\uvec{\vect r}\right)\ushD lm\left(\uvec K\right)
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
so
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)\ushD{l'}{m'}\left(\uvec r\right)=-\frac{1}{2\pi\mathcal{A}}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\frac{1}{2\pi\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\vect s}\sum_{lm}4\pi i^{l}j_{l}\left(\left|\vect K\right|\left|\vect r\right|\right)\ushD lm\left(\uvec r\right)\ush lm\left(\uvec K\right)\int_{\kappa^{2}\gamma_{\vect K}^{2}/4\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\tau}e^{-\left|\vect s_{\bot}+\vect r_{\bot}\right|^{2}\kappa^{2}\gamma_{\vect K}^{2}/4\tau}\tau^{-1}\ud\tau
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
We also have
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
e^{-\left|\vect s_{\bot}+\vect r_{\bot}\right|^{2}\kappa^{2}\gamma_{\vect K}^{2}/4\tau} & =e^{-\left(\left|\vect s_{\bot}\right|^{2}+\left|\vect r_{\bot}\right|^{2}+2\vect r_{\bot}\cdot\vect s_{\bot}\right)\kappa^{2}\gamma_{\vect K}^{2}/4\tau}\\
|
||||
& =e^{-\left|\vect s_{\bot}\right|^{2}\kappa^{2}\gamma_{\vect K}^{2}/4\tau}\sum_{n=0}^{\infty}\frac{1}{n!}\left(-\frac{\left(\left|\vect r_{\bot}\right|^{2}+2\vect r_{\bot}\cdot\vect s_{\bot}\right)\kappa^{2}\gamma_{\vect K}^{2}}{4\tau}\right)^{n},
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
hence
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)\ushD{l'}{m'}\left(\uvec r\right) & =-\frac{1}{2\pi\mathcal{A}}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\vect s}\sum_{lm}4\pi i^{l}j_{l}\left(\left|\vect K\right|\left|\vect r\right|\right)\ushD lm\left(\uvec r\right)\ush lm\left(\uvec K\right)\sum_{n=0}^{\infty}\frac{1}{n!}\left(-\frac{\left(\left|\vect r_{\bot}\right|^{2}+2\vect r_{\bot}\cdot\vect s_{\bot}\right)\kappa^{2}\gamma_{\vect K}^{2}}{4}\right)^{n}\underbrace{\int_{\kappa^{2}\gamma_{\vect K}^{2}/4\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\tau}e^{-\left|\vect s_{\bot}\right|^{2}\kappa^{2}\gamma_{\vect K}^{2}/4\tau}\tau^{-1-n}\ud\tau}_{\Delta_{n+1/2}}\\
|
||||
& =-\frac{1}{2\pi\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\vect s}\sum_{lm}4\pi i^{l}j_{l}\left(\left|\vect K\right|\left|\vect r\right|\right)\ush lm\left(\uvec K\right)\sum_{n=0}^{\infty}\frac{\Delta_{n+1/2}}{n!}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left(-\frac{\left(\left|\vect r_{\bot}\right|^{2}+2\vect r_{\bot}\cdot\vect s_{\bot}\right)\kappa^{2}\gamma_{\vect K}^{2}}{4}\right)^{n}\\
|
||||
& =-\frac{1}{2\pi\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\vect s}\sum_{lm}4\pi i^{l}j_{l}\left(\left|\vect K\right|\left|\vect r\right|\right)\ush lm\left(\uvec K\right)\sum_{n=0}^{\infty}\frac{\left(-1\right)^{n}}{n!}\Delta_{n+1/2}\left(\frac{\kappa\gamma_{\vect K}}{2}\right)^{2n}\sum_{k=0}^{n}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left|\vect r_{\bot}\right|^{2(n-k)}\left(2\vect r_{\bot}\cdot\vect s_{\bot}\right)^{k}
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
If we label
|
||||
\begin_inset Formula $\left|\vect r_{\bot}\right|\left|\vect s_{\bot}\right|\cos\varphi\equiv\vect r_{\bot}\cdot\vect s_{\bot}$
|
||||
\end_inset
|
||||
|
||||
, we have
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)\ushD{l'}{m'}\left(\uvec r\right)=-\frac{1}{2\pi\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\vect s}\sum_{lm}4\pi i^{l}j_{l}\left(\left|\vect K\right|\left|\vect r\right|\right)\ush lm\left(\uvec K\right)\sum_{n=0}^{\infty}\frac{\left(-1\right)^{n}}{n!}\Delta_{n+1/2}\left(\frac{\kappa\gamma_{\vect K}}{2}\right)^{2n}\sum_{k=0}^{n}\left(2\left|\vect s_{\bot}\right|\right)^{k}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left|\vect r_{\bot}\right|^{2n-k}\left(\cos\varphi\right)^{k}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
and if we label
|
||||
\begin_inset Formula $\left|\vect r\right|\sin\vartheta\equiv\left|\vect r_{\bot}\right|$
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)\ushD{l'}{m'}\left(\uvec r\right)=-\frac{1}{2\pi\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\vect s}\sum_{lm}4\pi i^{l}j_{l}\left(\left|\vect K\right|\left|\vect r\right|\right)\ush lm\left(\uvec K\right)\sum_{n=0}^{\infty}\frac{\left(-1\right)^{n}}{n!}\Delta_{n+1/2}\left(\frac{\kappa\gamma_{\vect K}}{2}\right)^{2n}\sum_{k=0}^{n}\left|\vect r\right|^{2n-k}\left(2\left|\vect s_{\bot}\right|\right)^{k}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left(\sin\vartheta\right)^{2n-k}\left(\cos\varphi\right)^{k}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Now let's put the RHS into
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand eqref
|
||||
reference "eq:tau extraction formula"
|
||||
plural "false"
|
||||
caps "false"
|
||||
noprefix "false"
|
||||
|
||||
\end_inset
|
||||
|
||||
and try eliminating some sum by taking the limit
|
||||
\begin_inset Formula $\left|\vect r\right|\to0$
|
||||
\end_inset
|
||||
|
||||
.
|
||||
We have
|
||||
\begin_inset Formula $j_{l}\left(\left|\vect K\right|\left|\vect r\right|\right)\sim\left(\left|\vect K\right|\left|\vect r\right|\right)^{l}/\left(2l+1\right)!!$
|
||||
\end_inset
|
||||
|
||||
; the denominator from
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand eqref
|
||||
reference "eq:tau extraction formula"
|
||||
plural "false"
|
||||
caps "false"
|
||||
noprefix "false"
|
||||
|
||||
\end_inset
|
||||
|
||||
behaves like
|
||||
\begin_inset Formula $j_{l'}\left(\kappa\left|\vect r\right|\right)\sim\left(\kappa\left|\vect r\right|\right)^{l'}/\left(2l'+1\right)!!.$
|
||||
\end_inset
|
||||
|
||||
The leading terms are hence those with
|
||||
\begin_inset Formula $\left|\vect r\right|^{l-l'+2n-k}$
|
||||
\end_inset
|
||||
|
||||
.
|
||||
So
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\tau_{l'}^{m'}\left(\vect s,\vect k\right)=\frac{-i}{2\pi\mathcal{A}\kappa^{1+l'}}\left(2l'+1\right)!!\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\vect s}\sum_{lm}4\pi i^{l}\frac{\left|\vect K\right|^{l}}{\left(2l+1\right)!!}\ush lm\left(\uvec K\right)\sum_{n=0}^{\infty}\frac{\left(-1\right)^{n}}{n!}\Delta_{n+1/2}\left(\frac{\kappa\gamma_{\vect K}}{2}\right)^{2n}\sum_{k=0}^{n}\delta_{l'-l,2n-k}\left(2\left|\vect s_{\bot}\right|\right)^{k}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left(\sin\vartheta\right)^{l'-l}\left(\cos\varphi\right)^{k}.
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Let's now focus on rearranging the sums; we have
|
||||
\begin_inset Formula
|
||||
\[
|
||||
S(l')\equiv\sum_{l=0}^{\infty}\sum_{n=0}^{\infty}\sum_{k=0}^{n}\delta_{l'-l,2n-k}f(l',l,n,k)=\sum_{l=0}^{\infty}\sum_{n=0}^{\infty}\sum_{k=0}^{n}\delta_{l'-l,2n-k}f(l',l,n,2n-l'+l)
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
We have
|
||||
\begin_inset Formula $0\le k\le n$
|
||||
\end_inset
|
||||
|
||||
, hence
|
||||
\begin_inset Formula $0\le2n-l'+l\le n$
|
||||
\end_inset
|
||||
|
||||
, hence
|
||||
\begin_inset Formula $-2n\le-l'+l\le-n$
|
||||
\end_inset
|
||||
|
||||
, hence also
|
||||
\begin_inset Formula $l'-2n\le l\le l'-n$
|
||||
\end_inset
|
||||
|
||||
, which gives the opportunity to swap the
|
||||
\begin_inset Formula $l,n$
|
||||
\end_inset
|
||||
|
||||
sums and the
|
||||
\begin_inset Formula $l$
|
||||
\end_inset
|
||||
|
||||
-sum becomes finite; so also consuming
|
||||
\begin_inset Formula $\sum_{k=0}^{n}\delta_{l'-l,2n-k}$
|
||||
\end_inset
|
||||
|
||||
we get
|
||||
\begin_inset Formula
|
||||
\[
|
||||
S(l')=\sum_{n=0}^{\infty}\sum_{l=\max(0,l'-2n)}^{l'-n}f(l',l,n,2n-l'+l).
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Finally, we see that the interval of valid
|
||||
\begin_inset Formula $l$
|
||||
\end_inset
|
||||
|
||||
becomes empty when
|
||||
\begin_inset Formula $l'-n<0$
|
||||
\end_inset
|
||||
|
||||
, i.e.
|
||||
|
||||
\begin_inset Formula $n>l'$
|
||||
\end_inset
|
||||
|
||||
; so we get a finite sum
|
||||
\begin_inset Formula
|
||||
\[
|
||||
S(l')=\sum_{n=0}^{l'}\sum_{l=\max(0,l'-2n)}^{l'-n}f(l',l,n,2n-l'+l).
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Applying rearrangement,
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\tau_{l'}^{m'}\left(\vect s,\vect k\right)=\frac{-i}{2\pi\mathcal{A}\kappa^{1+l'}}\left(2l'+1\right)!!\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\vect s}\sum_{n=0}^{l'}\frac{\left(-1\right)^{n}}{n!}\Delta_{n+1/2}\left(\frac{\kappa\gamma_{\vect K}}{2}\right)^{2n}\sum_{l=\max\left(0,l'-2n\right)}^{l'-n}4\pi i^{l}\left(2\left|\vect s_{\bot}\right|\right)^{2n-l'+l}\frac{\left|\vect K\right|^{l}}{\left(2l+1\right)!!}\sum_{m=-l}^{l}\ush lm\left(\uvec K\right)\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left(\sin\vartheta\right)^{l'-l}\left(\cos\varphi\right)^{2n-l'+l}.
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Section
|
||||
Z-aligned lattice
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Now we set some conventions: let the lattice lie on the
|
||||
\begin_inset Formula $z$
|
||||
\end_inset
|
||||
|
||||
axis, so that
|
||||
\begin_inset Formula $\vect s_{\bot},\vect r_{\bot}$
|
||||
\end_inset
|
||||
|
||||
lie in the
|
||||
\begin_inset Formula $xy$
|
||||
\end_inset
|
||||
|
||||
-plane.
|
||||
\begin_inset Note Note
|
||||
status open
|
||||
|
||||
\begin_layout Plain Layout
|
||||
(TODO check the meaning of
|
||||
\begin_inset Formula $\vect k$
|
||||
\end_inset
|
||||
|
||||
and possible additional phase factor.)
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
If we write
|
||||
\begin_inset Formula $\vect s_{\bot}=\uvec x\left|\vect s_{\bot}\right|\cos\Phi+\uvec y\left|\vect s_{\bot}\right|\sin\Phi$
|
||||
\end_inset
|
||||
|
||||
,
|
||||
\begin_inset Formula $\vect r_{\bot}=\uvec x\left|\vect r_{\bot}\right|\cos\phi+\uvec y\left|\vect r_{\bot}\right|\sin\phi=\uvec x\left|\vect r\right|\sin\theta\cos\phi+\uvec y\left|\vect r\right|\sin\theta\sin\phi$
|
||||
\end_inset
|
||||
|
||||
, we have
|
||||
\begin_inset Formula $\varphi=\phi-\Phi$
|
||||
\end_inset
|
||||
|
||||
, and
|
||||
\begin_inset Formula $\vartheta=\theta$
|
||||
\end_inset
|
||||
|
||||
.
|
||||
Also, in this convention
|
||||
\begin_inset Formula $\ush lm\left(\uvec K\right)=0$
|
||||
\end_inset
|
||||
|
||||
for
|
||||
\begin_inset Formula $m\ne0$
|
||||
\end_inset
|
||||
|
||||
, so
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\tau_{l'}^{m'}\left(\vect s,\vect k\right)=\frac{-i}{2\pi\mathcal{A}\kappa^{1+l'}}\left(2l'+1\right)!!\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\vect s}\sum_{n=0}^{l'}\frac{\left(-1\right)^{n}}{n!}\Delta_{n+1/2}\left(\frac{\kappa\gamma_{\vect K}}{2}\right)^{2n}\sum_{l=\max\left(0,l'-2n\right)}^{l'-n}4\pi i^{l}\left(2\left|\vect s_{\bot}\right|\right)^{2n-l'+l}\frac{\left|\vect K\right|^{l}}{\left(2l+1\right)!!}\ush l0\left(\uvec K\right)\underbrace{\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD l0\left(\uvec r\right)\left(\sin\theta\right)^{l'-l}\left(\cos\varphi\right)^{2n-l'+l}}_{\equiv A_{l',l,n,m'}}.
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Let's also fix the (dual) spherical harmonics for now,
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\ushD lm\left(\uvec r\right)=\lambda'_{lm}e^{-im\phi}P_{l}^{-m}\left(\cos\theta\right);
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
the angular integral then becomes (we also use
|
||||
\begin_inset Formula $e^{-im'\phi}=e^{im'\Phi}e^{-im'\varphi}$
|
||||
\end_inset
|
||||
|
||||
)
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
A_{l',l,n,m'} & \equiv\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD l0\left(\uvec r\right)\left(\sin\theta\right)^{l'-l}\left(\cos\varphi\right)^{2n-l'+l}\\
|
||||
& =\lambda'_{l'm'}\lambda'_{l0}e^{im'\Phi}\int_{0}^{\pi}\ud\theta\,\sin\theta P_{l'}^{-m'}\left(\cos\theta\right)P_{l}^{0}\left(\cos\theta\right)\left(\sin\theta\right)^{l'-l}\int_{0}^{2\pi}\ud\varphi\,e^{-im'\varphi}\left(\cos\varphi\right)^{2n-l'+l}.
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
The asimuthal integral evaluates to
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\int_{0}^{2\pi}\ud\varphi\,e^{-im'\varphi}\left(\cos\varphi\right)^{2n-l'+l}=\pi\delta_{\left|m'\right|,2n-l'+l}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
(note that
|
||||
\begin_inset Formula $2n-l'+l\ge0$
|
||||
\end_inset
|
||||
|
||||
as it's the former index
|
||||
\begin_inset Formula $k$
|
||||
\end_inset
|
||||
|
||||
).
|
||||
That eliminates one of the two remaining (finite) sums.
|
||||
We are left with the polar integral
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\int_{0}^{\pi}\ud\theta\,\sin\theta P_{l'}^{-m'}\left(\cos\theta\right)P_{l}^{0}\left(\cos\theta\right)\left(\sin\theta\right)^{l'-l}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
for which I couldn't find an explicit form yet.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Section
|
||||
X-aligned lattice
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
If we instead set
|
||||
\begin_inset Formula $\vect s_{\bot}=\uvec z\left|\vect s_{\bot}\right|\cos\Theta+\uvec y\left|\vect s_{\bot}\right|\sin\Theta$
|
||||
\end_inset
|
||||
|
||||
,
|
||||
\begin_inset Formula $\vect r_{\bot}=\uvec z\left|\vect r_{\bot}\right|\cos\theta+\uvec y\left|\vect r_{\bot}\right|\sin\theta=\uvec z\left|\vect r\right|\cos\theta+\uvec y\left|\vect r\right|\sin\theta\sin\phi$
|
||||
\end_inset
|
||||
|
||||
, we have
|
||||
\begin_inset Formula $\vartheta=\Theta-\theta$
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD lm\left(\uvec r\right)\left(\sin\vartheta\right)^{l'-l}\left(\cos\varphi\right)^{k}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Note Note
|
||||
status open
|
||||
|
||||
\begin_layout Plain Layout
|
||||
BTW:
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
\left|\vect r_{\bot}\right|^{2} & =\left|\vect r\right|^{2}-\left|\vect r_{\parallel}\right|^{2}=\left|\vect r\right|^{2}-\left(\vect r\cdot\uvec K\right)^{2},\\
|
||||
\vect r_{\bot}\cdot\vect s_{\bot} & =\vect r\cdot\vect s_{\bot}
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Note Note
|
||||
status open
|
||||
|
||||
\begin_layout Plain Layout
|
||||
Now we set the conventions: let the lattice lie on the
|
||||
\begin_inset Formula $z$
|
||||
\end_inset
|
||||
|
||||
axis, so that
|
||||
\begin_inset Formula $\vect s_{\bot},\vect r_{\bot}$
|
||||
\end_inset
|
||||
|
||||
lie in the
|
||||
\begin_inset Formula $xy$
|
||||
\end_inset
|
||||
|
||||
-plane, (TODO check the meaning of
|
||||
\begin_inset Formula $\vect k$
|
||||
\end_inset
|
||||
|
||||
and possible additional phase factor.) If we write
|
||||
\begin_inset Formula $\vect s_{\bot}=\uvec xs_{\bot}\cos\Phi+\uvec ys_{\bot}\sin\Phi$
|
||||
\end_inset
|
||||
|
||||
,
|
||||
\begin_inset Formula $\vect r_{\bot}=\uvec xr_{\bot}\cos\phi+\uvec yr_{\bot}\sin\phi=\uvec xr\sin\theta\cos\phi+\uvec yr\sin\theta\sin\phi$
|
||||
\end_inset
|
||||
|
||||
, we have
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\left|\vect s_{\bot}+\vect r_{\bot}\right|^{2}=s_{\bot}^{2}+r^{2}\left(\sin\theta\right)^{2}+2s_{\bot}r\sin\theta\cos\left(\phi-\Phi\right).
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Plain Layout
|
||||
Also, in this convention
|
||||
\begin_inset Formula $\ush lm\left(\uvec K\right)=0$
|
||||
\end_inset
|
||||
|
||||
for
|
||||
\begin_inset Formula $m\ne0$
|
||||
\end_inset
|
||||
|
||||
, so
|
||||
\end_layout
|
||||
|
||||
\begin_layout Plain Layout
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)\ushD{l'}{m'}\left(\uvec r\right) & =-\frac{1}{2\pi\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\vect s}\sum_{lm}4\pi i^{l}j_{l}\left(\left|\vect K\right|\left|\vect r\right|\right)\ush l0\left(\uvec K\right)\times\\
|
||||
& \quad\times\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\ushD l0\left(\uvec r\right)\sum_{n=0}^{\infty}\Delta_{n+1/2}\frac{1}{n!}\left(-\frac{\left(\left|\vect r_{\bot}\right|^{2}+2\vect r_{\bot}\cdot\vect s_{\bot}\right)\kappa^{2}\gamma_{\vect K}^{2}}{4}\right)^{n}.
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
Let's also fix the spherical harmonics for now,
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\ushD lm\left(\uvec r\right)=\lambda'_{lm}e^{-im\phi}P_{l}^{-m}\left(\cos\theta\right)
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Also, in this convention
|
||||
\begin_inset Formula $\ush lm\left(\uvec K\right)=0$
|
||||
\end_inset
|
||||
|
||||
for
|
||||
\begin_inset Formula $m\ne0$
|
||||
\end_inset
|
||||
|
||||
, so
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\int\ud\Omega_{\vect r}\,G_{\Lambda}^{(1;\kappa)}\left(\vect s+\vect r\right)\ushD{l'}{m'}\left(\uvec r\right)=-\frac{1}{2\pi\mathcal{A}}\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)\frac{1}{2\pi\mathcal{A}}\sum_{\vect K\in\Lambda^{*}}e^{i\vect K\cdot\vect s}\sum_{l}4\pi i^{l}j_{l}\left(\left|\vect K\right|\left|\vect r\right|\right)\ushD l0\left(\uvec r\right)\ush l0\left(\uvec K\right)\int_{\kappa^{2}\gamma_{\vect K}^{2}/4\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\tau}e^{-\left(s_{\bot}^{2}+r_{\bot}^{2}+2s_{\bot}r_{\bot}\cos\left(\phi-\Phi\right)\right)^{2}\kappa^{2}\gamma_{\vect K}^{2}/4\tau}\tau^{-1}\ud\tau
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Plain Layout
|
||||
Let's also fix the spherical harmonics for now,
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\ushD lm\left(\uvec r\right)=\lambda'_{lm}e^{-im\phi}P_{l}^{-m}\left(\cos\theta\right)
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Plain Layout
|
||||
The angular integral (assuming it can be separated from the rest like this)
|
||||
is
|
||||
\begin_inset Formula
|
||||
\[
|
||||
I_{l'}^{m'}\equiv\int\ud\Omega_{\vect r}\,\ushD{l'}{m'}\left(\uvec r\right)e^{-\left(r_{\bot}^{2}+2s_{\bot}r_{\bot}\cos\left(\phi-\Phi\right)\right)^{2}\kappa^{2}\gamma_{\vect K}^{2}/4\tau}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Plain Layout
|
||||
Let's further extract the azimuthal part
|
||||
\begin_inset Formula $\left(w\equiv2r_{\bot}s_{\bot}\kappa^{2}\gamma_{\vect K}^{2}/4\tau\right)$
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
e^{-im'\Phi}A_{l'}^{m'}\equiv\int_{0}^{2\pi}e^{-im'\phi}e^{-w\cos\left(\phi-\Phi\right)}\ud\phi=e^{-im'\Phi}\int_{0}^{2\pi}e^{-im'\varphi}e^{-w\cos\varphi}\ud\varphi
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Using [DLMF 10.9.2],
|
||||
\begin_inset Formula $\int_{0}^{2\pi}e^{-im'\varphi}e^{-w\cos\varphi}\ud\varphi=\int_{0}^{2\pi}\cos\left(m'\varphi\right)e^{i(iw)\cos\varphi}=2\pi i^{m'}J_{m'}\left(iw\right)$
|
||||
\end_inset
|
||||
|
||||
we have
|
||||
\begin_inset Formula
|
||||
\[
|
||||
e^{-m'\Phi}A_{l'}^{m'}=2\pi i^{m'}J_{m'}\left(iw\right),
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
assuming that
|
||||
\begin_inset Formula $w$
|
||||
\end_inset
|
||||
|
||||
is real (which does not necessarily have to be true!); numerical experiments
|
||||
in Sage show that the result is valid also for complex
|
||||
\begin_inset Formula $w$
|
||||
\end_inset
|
||||
|
||||
.
|
||||
\begin_inset Note Note
|
||||
status collapsed
|
||||
|
||||
\begin_layout Plain Layout
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
A_{l}^{m} & =\int_{0}^{2\pi}e^{-im\varphi}\sum_{n=0}^{\infty}\frac{\left(-w\cos\varphi\right)^{n}}{n!}\ud\varphi\\
|
||||
& =\int_{0}^{2\pi}e^{-im\varphi}\sum_{n=0}^{\infty}\frac{\left(-w\right)^{n}}{2^{n}n!}\left(e^{i\varphi}+e^{-i\varphi}\right)^{n}\ud\varphi\\
|
||||
& =\sum_{n=0}^{\infty}\frac{\left(-w\right)^{n}}{2^{n}n!}\int_{0}^{2\pi}e^{-im\varphi}\sum_{k=0}^{n}\binom{n}{k}e^{ik\varphi}e^{-i\left(n-k\right)\varphi}\ud\varphi\\
|
||||
& =\sum_{n=0}^{\infty}\frac{\left(-w\right)^{n}}{2^{n}n!}\sum_{k=0}^{n}\binom{n}{k}\int_{0}^{2\pi}e^{i\left(2k-n-m\right)\varphi}\ud\varphi\\
|
||||
& =2\pi\sum_{n=0}^{\infty}\frac{\left(-w\right)^{n}}{2^{n}n!}\sum_{k=0}^{n}\binom{n}{k}\delta_{2k-n-m=0}\\
|
||||
& =2\pi\sum_{n=0}^{\infty}\frac{\left(-w\right)^{n}}{2^{n}n!}\sum_{k=0}^{n}\binom{n}{k}\delta_{2k-n-m=0}\\
|
||||
& =2\pi\sum_{k=0}^{\infty}\sum_{n=k}^{\infty}\frac{\left(-w\right)^{n}}{2^{n}n!}\binom{n}{k}\delta_{2k-n-m=0}\\
|
||||
& =2\pi\sum_{k=0}^{\infty}\frac{\left(-w\right)^{2k-m}}{2^{2k-m}\left(2k-m\right)!}\binom{2k-m}{k}\delta_{2k-m\ge k}\\
|
||||
& =2\pi\sum_{k=0}^{\infty}\frac{\left(-w\right)^{2k-m}}{2^{2k-m}}\frac{1}{k!\left(k-m\right)!}\delta_{k-m\ge0}\\
|
||||
& =2\pi\sum_{k=\max\left(m,0\right)}^{\infty}\left(-\frac{w}{2}\right)^{2k-m}\frac{1}{k!\left(k-m\right)!}
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Note Note
|
||||
status collapsed
|
||||
|
||||
\begin_layout Plain Layout
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
A_{l}^{m} & =\int_{0}^{2\pi}e^{-im\varphi}\sum_{n=0}^{\infty}\frac{\left(-w\cos\varphi\right)^{n}}{n!}\ud\varphi\\
|
||||
& =\int_{0}^{2\pi}e^{-im\varphi}\sum_{n=0}^{\infty}\frac{\left(-w\right)^{n}}{2^{n}n!}\left(e^{i\varphi}+e^{-i\varphi}\right)^{n}\ud\varphi\\
|
||||
& =\sum_{n=0}^{\infty}\frac{\left(-w\right)^{n}}{2^{n}n!}\int_{0}^{2\pi}e^{-im\varphi}\sum_{k=0}^{n}\binom{n}{k}e^{i\left(n-k\right)\varphi}e^{-ik\varphi}\ud\varphi\\
|
||||
& =\sum_{n=0}^{\infty}\frac{\left(-w\right)^{n}}{2^{n}n!}\sum_{k=0}^{n}\binom{n}{k}\int_{0}^{2\pi}e^{i\left(-2k+n-m\right)\varphi}\ud\varphi\\
|
||||
& =2\pi\sum_{n=0}^{\infty}\frac{\left(-w\right)^{n}}{2^{n}n!}\sum_{k=0}^{n}\binom{n}{k}\delta_{-2k+n-m=0}\\
|
||||
& =2\pi\sum_{n=0}^{\infty}\frac{\left(-w\right)^{n}}{2^{n}n!}\sum_{k=0}^{n}\binom{n}{k}\delta_{-2k+n-m=0}\\
|
||||
& =2\pi\sum_{k=0}^{\infty}\sum_{n=k}^{\infty}\frac{\left(-w\right)^{n}}{2^{n}n!}\binom{n}{k}\delta_{-2k+n-m=0}\\
|
||||
& =2\pi\sum_{k=0}^{\infty}\frac{\left(-w\right)^{2k+m}}{2^{2k+m}\left(2k+m\right)!}\binom{2k+m}{k}\delta_{2k+m\ge k}\\
|
||||
& =2\pi\sum_{k=0}^{\infty}\frac{\left(-w\right)^{2k+m}}{2^{2k+m}}\frac{1}{k!\left(k+m\right)!}\delta_{k+m\ge0}\\
|
||||
& =2\pi\sum_{k=\max\left(-m,0\right)}^{\infty}\frac{\left(-w\right)^{2k+m}}{2^{2k+m}}\frac{1}{k!\left(k+m\right)!}
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
Althought it's not superobvious, this sum is symmetric w.r.t.
|
||||
sign change in
|
||||
\begin_inset Formula $m$
|
||||
\end_inset
|
||||
|
||||
.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Plain Layout
|
||||
Let's do the polar integration next:
|
||||
\begin_inset Formula $r_{\bot}=r\sin\theta$
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
B_{l'}^{m'}\equiv\int_{0}^{\pi}\sin\theta\ud\theta\,P_{l'}^{-m'}\left(\cos\theta\right)P_{l}^{0}\left(\cos\theta\right)e^{-\left(\sin\theta\right)^{2}r^{2}\kappa^{2}\gamma_{\vect K}^{2}/4\tau}\left(-\sin\theta\,rs_{\bot}\kappa^{2}\gamma_{\vect K}^{2}/4\tau\right)^{2k-m'}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Label
|
||||
\begin_inset Formula $u\equiv r^{2}\kappa^{2}\gamma_{\vect K}^{2}/4\tau,v\equiv rs_{\bot}\kappa^{2}\gamma_{\vect K}^{2}/4\tau$
|
||||
\end_inset
|
||||
|
||||
; then
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
B_{l'}^{m'} & =\int_{0}^{\pi}\sin\theta\ud\theta\,P_{l'}^{-m'}\left(\cos\theta\right)P_{l}^{0}\left(\cos\theta\right)e^{-u\left(\sin\theta\right)^{2}}\left(-v\sin\theta\right)^{2k-m'}\\
|
||||
& =\int_{0}^{\pi}\sin\theta\ud\theta\,P_{l'}^{-m'}\left(\cos\theta\right)P_{l}^{0}\left(\cos\theta\right)\left(-v\sin\theta\right)^{2k-m'}\sum_{a=0}^{\infty}\frac{\left(-u\right)^{a}}{a!}\left(\sin\theta\right)^{2a}\\
|
||||
& =\left(-v\right)^{2k-m'}\sum_{a=0}^{\infty}\frac{\left(-u\right)^{a}}{a!}\int_{0}^{\pi}\sin\theta\ud\theta\,P_{l'}^{-m'}\left(\cos\theta\right)P_{l}^{0}\left(\cos\theta\right)\left(\sin\theta\right)^{2a+2k-m'}
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
If we now perform the limit
|
||||
\begin_inset Formula $r\to0$
|
||||
\end_inset
|
||||
|
||||
and compare the radial parts (incl.
|
||||
those in
|
||||
\begin_inset Formula $u,v$
|
||||
\end_inset
|
||||
|
||||
) powers, the leading term indices will have
|
||||
\begin_inset Formula
|
||||
\[
|
||||
l'\sim l+2a+2k-m'
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
so we can fix
|
||||
\begin_inset Formula $2a+2k-m'=l'-l$
|
||||
\end_inset
|
||||
|
||||
and get
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\int_{0}^{\pi}\sin\theta\ud\theta\,P_{l'}^{-m'}\left(\cos\theta\right)P_{l}^{0}\left(\cos\theta\right)\left(\sin\theta\right)^{l'-l}=\begin{cases}
|
||||
0 & l'-l+m'\text{ odd}\\
|
||||
? & l'-l+m'\text{ even}
|
||||
\end{cases}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula $ $
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\end_body
|
||||
\end_document
|
|
@ -0,0 +1,305 @@
|
|||
#LyX 2.4 created this file. For more info see https://www.lyx.org/
|
||||
\lyxformat 584
|
||||
\begin_document
|
||||
\begin_header
|
||||
\save_transient_properties true
|
||||
\origin unavailable
|
||||
\textclass article
|
||||
\use_default_options true
|
||||
\maintain_unincluded_children false
|
||||
\language finnish
|
||||
\language_package default
|
||||
\inputencoding utf8
|
||||
\fontencoding auto
|
||||
\font_roman "default" "default"
|
||||
\font_sans "default" "default"
|
||||
\font_typewriter "default" "default"
|
||||
\font_math "auto" "auto"
|
||||
\font_default_family default
|
||||
\use_non_tex_fonts false
|
||||
\font_sc false
|
||||
\font_roman_osf false
|
||||
\font_sans_osf false
|
||||
\font_typewriter_osf false
|
||||
\font_sf_scale 100 100
|
||||
\font_tt_scale 100 100
|
||||
\use_microtype false
|
||||
\use_dash_ligatures true
|
||||
\graphics default
|
||||
\default_output_format default
|
||||
\output_sync 0
|
||||
\bibtex_command default
|
||||
\index_command default
|
||||
\paperfontsize default
|
||||
\use_hyperref false
|
||||
\papersize default
|
||||
\use_geometry false
|
||||
\use_package amsmath 1
|
||||
\use_package amssymb 1
|
||||
\use_package cancel 1
|
||||
\use_package esint 1
|
||||
\use_package mathdots 1
|
||||
\use_package mathtools 1
|
||||
\use_package mhchem 1
|
||||
\use_package stackrel 1
|
||||
\use_package stmaryrd 1
|
||||
\use_package undertilde 1
|
||||
\cite_engine basic
|
||||
\cite_engine_type default
|
||||
\use_bibtopic false
|
||||
\use_indices false
|
||||
\paperorientation portrait
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 1
|
||||
\use_minted 0
|
||||
\use_lineno 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
\end_index
|
||||
\secnumdepth 3
|
||||
\tocdepth 3
|
||||
\paragraph_separation indent
|
||||
\paragraph_indentation default
|
||||
\is_math_indent 0
|
||||
\math_numbering_side default
|
||||
\quotes_style english
|
||||
\dynamic_quotes 0
|
||||
\papercolumns 1
|
||||
\papersides 1
|
||||
\paperpagestyle default
|
||||
\tablestyle default
|
||||
\tracking_changes false
|
||||
\output_changes false
|
||||
\html_math_output 0
|
||||
\html_css_as_file 0
|
||||
\html_be_strict false
|
||||
\end_header
|
||||
|
||||
\begin_body
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
\lang english
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\uoft}[1]{\mathfrak{F}#1}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\uaft}[1]{\mathfrak{\mathbb{F}}#1}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\usht}[2]{\mathbb{S}_{#1}#2}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\bsht}[2]{\mathrm{S}_{#1}#2}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\sgn}{\operatorname{sgn}}
|
||||
{\mathrm{sgn}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\pht}[2]{\mathfrak{\mathbb{H}}_{#1}#2}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\vect}[1]{\mathbf{#1}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ud}{\mathrm{d}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\basis}[1]{\mathfrak{#1}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\dc}[1]{Ш_{#1}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\rec}[1]{#1^{-1}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\recb}[1]{#1^{\widehat{-1}}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ints}{\mathbb{Z}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\nats}{\mathbb{N}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\reals}{\mathbb{R}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ush}[2]{Y_{#1,#2}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\hgfr}{\mathbf{F}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\hgf}{F}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ghgf}[2]{\mbox{}_{#1}F_{#2}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ghgfr}[2]{\mbox{}_{#1}\mathbf{F}_{#2}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\ph}{\mathrm{ph}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\kor}[1]{\underline{#1}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\koru}[1]{\utilde{#1}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\swv}{\mathscr{H}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\expint}{\mathrm{E}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
\lang english
|
||||
\begin_inset Formula
|
||||
\begin{eqnarray}
|
||||
\sigma_{n}^{m(1)} & = & -\frac{i^{n+1}}{2k^{2}\mathscr{A}}\left(-1\right)^{\left(n+m\right)/2}\sqrt{\left(2n+1\right)\left(n-m\right)!\left(n+m\right)!}\times\nonumber \\
|
||||
& & \times\sum_{\vect K_{pq}\in\Lambda^{*}}^{'}\sum_{j=0}^{\left[\left(n-\left|m\right|/2\right)\right]}\frac{\left(-1\right)^{j}\left(\beta_{pq}/2k\right)^{n-2j}e^{im\phi_{\vect{\beta}_{pq}}}\Gamma_{j,pq}}{j!\left(\frac{1}{2}\left(n-m\right)-j\right)!\left(\frac{1}{2}\left(n+m\right)-j\right)!}\left(\frac{\gamma_{pq}}{2}\right)^{2j-1}\nonumber \\
|
||||
& = & -\frac{i^{n+1}}{2k^{2}\mathscr{A}}\sqrt{\pi}2^{n+1}\left(\left(n-m\right)/2\right)!\left(\left(n+m\right)/2\right)!\times\nonumber \\
|
||||
& & \times\sum_{\vect K_{pq}\in\Lambda^{*}}^{'}Y_{n}^{m}\left(\frac{\pi}{2},\phi_{\vect{\beta}_{pq}}\right)\sum_{j=0}^{\left[\left(n-\left|m\right|/2\right)\right]}\frac{\left(-1\right)^{j}\left(\beta_{pq}/2k\right)^{n-2j}\Gamma_{j,pq}}{j!\left(\frac{1}{2}\left(n-m\right)-j\right)!\left(\frac{1}{2}\left(n+m\right)-j\right)!}\left(\frac{\gamma_{pq}}{2}\right)^{2j-1}\nonumber \\
|
||||
& = & -\frac{i^{n+1}}{k^{2}\mathscr{A}}\sqrt{\pi}2\left(\left(n-m\right)/2\right)!\left(\left(n+m\right)/2\right)!\times\nonumber \\
|
||||
& & \times\sum_{\vect K_{pq}\in\Lambda^{*}}^{'}Y_{n}^{m}\left(\frac{\pi}{2},\phi_{\vect{\beta}_{pq}}\right)\sum_{j=0}^{\left[\left(n-\left|m\right|/2\right)\right]}\frac{\left(-1\right)^{j}\left(\beta_{pq}/k\right)^{n-2j}\Gamma_{j,pq}}{j!\left(\frac{1}{2}\left(n-m\right)-j\right)!\left(\frac{1}{2}\left(n+m\right)-j\right)!}\left(\gamma_{pq}\right)^{2j-1}\label{eq:2D Ewald in 3D long-range part}
|
||||
\end{eqnarray}
|
||||
|
||||
\end_inset
|
||||
|
||||
For
|
||||
\begin_inset Formula $z\ne0$
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
& =-\frac{i^{n+1}}{k^{2}\mathscr{A}}\sqrt{\pi}2\left(\left(n-m\right)/2\right)!\left(\left(n+m\right)/2\right)!\\
|
||||
& \times\sum_{\vect K_{pq}\in\Lambda^{*}}^{'}Y_{n}^{m}\left(\frac{\pi}{2},\phi_{\vect{\beta}_{pq}}\right)\sum_{j=0}^{n-\left|m\right|}\frac{\Delta_{npq}}{j!}\left(-1\right)^{j}\left(\gamma_{pq}\right)^{2j-1}\sum_{s\overset{*}{=}j}^{\min(2j,n-\left|m\right|)}\binom{j}{2j-s}\frac{\left(-\kappa z\right)^{2j-s}\left(\beta_{pq}/k\right)^{n-s}}{\left(\frac{1}{2}\left(n-m-s\right)\right)!\left(\frac{1}{2}\left(n+m-s\right)\right)!}\\
|
||||
& =-\frac{i^{n+1}}{k^{2}\mathscr{A}}\sqrt{\pi}2\left(\left(n-m\right)/2\right)!\left(\left(n+m\right)/2\right)!\\
|
||||
& \times\sum_{\vect K_{pq}\in\Lambda^{*}}^{'}Y_{n}^{m}\left(\frac{\pi}{2},\phi_{\vect{\beta}_{pq}}\right)\sum_{j=0}^{n-\left|m\right|}\Delta_{npq}\left(\gamma_{pq}\right)^{2j-1}\sum_{s\overset{*}{=}j}^{\min(2j,n-\left|m\right|)}\frac{\left(-1\right)^{j}}{\left(2j-s\right)!\left(s-j\right)!}\frac{\left(-\kappa z\right)^{2j-s}\left(\beta_{pq}/k\right)^{n-s}}{\left(\frac{1}{2}\left(n-m-s\right)\right)!\left(\frac{1}{2}\left(n+m-s\right)\right)!}
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Section
|
||||
|
||||
\lang english
|
||||
Ewald long range integral
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
\lang english
|
||||
Linton has (2.24):
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{\left(1\right)}\left(\vect r\right)=\frac{\pi^{-d_{c}/2}}{2\mathcal{A}}\sum_{\vect K_{m}\in\Lambda^{*}}e^{i\vect K_{m}\cdot\vect r}\int_{1/\eta}^{\infty\exp\left(i\pi/4\right)}e^{-\kappa^{2}\gamma_{m}^{2}\zeta^{2}/4}e^{-\left|\vect r_{\bot}\right|^{2}/\zeta^{2}}\zeta^{1-d_{c}}\ud\zeta
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Try substitution
|
||||
\begin_inset Formula $t=\zeta^{2}$
|
||||
\end_inset
|
||||
|
||||
: then
|
||||
\begin_inset Formula $\ud t=2\zeta\,\ud\zeta$
|
||||
\end_inset
|
||||
|
||||
(
|
||||
\begin_inset Formula $\ud\zeta=\ud t/2t^{1/2}$
|
||||
\end_inset
|
||||
|
||||
) and
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{\left(1\right)}\left(\vect r\right)=\frac{\pi^{-d_{c}/2}}{4\mathcal{A}}\sum_{\vect K_{m}\in\Lambda^{*}}e^{i\vect K_{m}\cdot\vect r}\int_{1/\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\kappa^{2}\gamma_{m}^{2}t/4}e^{-\left|\vect r_{\bot}\right|^{2}/t}t^{\frac{-d_{c}}{2}}\ud t
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
Try subst.
|
||||
|
||||
\begin_inset Formula $\tau=k^{2}\gamma_{m}^{2}/4$
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
\lang english
|
||||
\begin_inset Formula
|
||||
\[
|
||||
G_{\Lambda}^{\left(1\right)}\left(\vect r\right)=\frac{\pi^{-d_{c}/2}}{4\mathcal{A}}\sum_{\vect K_{m}\in\Lambda^{*}}e^{i\vect K_{m}\cdot\vect r}\left(\frac{\kappa\gamma_{m}}{2}\right)^{d_{c}}\int_{\kappa^{2}\gamma_{m}^{2}/4\eta^{2}}^{\infty\exp\left(i\pi/2\right)}e^{-\tau}e^{-\left|\vect r_{\bot}\right|^{2}\kappa^{2}\gamma_{m}^{2}/4\tau}\tau^{\frac{-d_{c}}{2}}\ud\tau
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\end_body
|
||||
\end_document
|
|
@ -0,0 +1,386 @@
|
|||
#LyX 2.4 created this file. For more info see https://www.lyx.org/
|
||||
\lyxformat 584
|
||||
\begin_document
|
||||
\begin_header
|
||||
\save_transient_properties true
|
||||
\origin unavailable
|
||||
\textclass article
|
||||
\use_default_options true
|
||||
\maintain_unincluded_children false
|
||||
\language finnish
|
||||
\language_package default
|
||||
\inputencoding utf8
|
||||
\fontencoding auto
|
||||
\font_roman "default" "default"
|
||||
\font_sans "default" "default"
|
||||
\font_typewriter "default" "default"
|
||||
\font_math "auto" "auto"
|
||||
\font_default_family default
|
||||
\use_non_tex_fonts false
|
||||
\font_sc false
|
||||
\font_roman_osf false
|
||||
\font_sans_osf false
|
||||
\font_typewriter_osf false
|
||||
\font_sf_scale 100 100
|
||||
\font_tt_scale 100 100
|
||||
\use_microtype false
|
||||
\use_dash_ligatures true
|
||||
\graphics default
|
||||
\default_output_format default
|
||||
\output_sync 0
|
||||
\bibtex_command default
|
||||
\index_command default
|
||||
\paperfontsize default
|
||||
\use_hyperref false
|
||||
\papersize default
|
||||
\use_geometry false
|
||||
\use_package amsmath 1
|
||||
\use_package amssymb 1
|
||||
\use_package cancel 1
|
||||
\use_package esint 1
|
||||
\use_package mathdots 1
|
||||
\use_package mathtools 1
|
||||
\use_package mhchem 1
|
||||
\use_package stackrel 1
|
||||
\use_package stmaryrd 1
|
||||
\use_package undertilde 1
|
||||
\cite_engine basic
|
||||
\cite_engine_type default
|
||||
\use_bibtopic false
|
||||
\use_indices false
|
||||
\paperorientation portrait
|
||||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 1
|
||||
\use_minted 0
|
||||
\use_lineno 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
\end_index
|
||||
\secnumdepth 3
|
||||
\tocdepth 3
|
||||
\paragraph_separation indent
|
||||
\paragraph_indentation default
|
||||
\is_math_indent 0
|
||||
\math_numbering_side default
|
||||
\quotes_style english
|
||||
\dynamic_quotes 0
|
||||
\papercolumns 1
|
||||
\papersides 1
|
||||
\paperpagestyle default
|
||||
\tablestyle default
|
||||
\tracking_changes false
|
||||
\output_changes false
|
||||
\html_math_output 0
|
||||
\html_css_as_file 0
|
||||
\html_be_strict false
|
||||
\end_header
|
||||
|
||||
\begin_body
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
\lang english
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\vect}[1]{\mathbf{#1}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\lang finnish
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\Kambe}[1]{#1^{\mathrm{K}}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset FormulaMacro
|
||||
\newcommand{\Linton}[1]{#1^{\mathrm{L}}}
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Here and in Kambe's papers,
|
||||
\begin_inset Formula $\kappa$
|
||||
\end_inset
|
||||
|
||||
is the wavenumber (
|
||||
\begin_inset Formula $k$
|
||||
\end_inset
|
||||
|
||||
in Linton).
|
||||
Here
|
||||
\begin_inset Formula $\vect K_{p}$
|
||||
\end_inset
|
||||
|
||||
is a point of the reciprocal lattice (
|
||||
\begin_inset Formula $\vect K_{p}=\Kambe{\vect K_{pt}}=\Linton{\vect{\beta}_{\mu}}$
|
||||
\end_inset
|
||||
|
||||
)
|
||||
\end_layout
|
||||
|
||||
\begin_layout Section
|
||||
\begin_inset Quotes eld
|
||||
\end_inset
|
||||
|
||||
Gammas
|
||||
\begin_inset Quotes erd
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
For
|
||||
\begin_inset Formula $\kappa$
|
||||
\end_inset
|
||||
|
||||
positive,
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\Kambe{\Gamma_{p}}\equiv\begin{cases}
|
||||
\sqrt{\kappa^{2}-\left|\vect K_{p}\right|^{2}} & \kappa^{2}-\left|\vect K_{p}\right|^{2}>0\\
|
||||
i\sqrt{\left|\vect K_{p}\right|^{2}-\kappa^{2}} & \kappa^{2}-\left|\vect K_{p}\right|^{2}<0
|
||||
\end{cases}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\Linton{\gamma_{\mu}}\equiv\begin{cases}
|
||||
\sqrt{\left(\frac{\vect K_{p}}{\kappa}\right)^{2}-1} & \kappa-\left|\vect K_{p}\right|\le0\\
|
||||
-i\sqrt{1-\left(\frac{\vect K_{p}}{\kappa}\right)^{2}} & \kappa-\left|\vect K_{p}\right|>0
|
||||
\end{cases}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
hence
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\Kambe{\Gamma_{p}}=-i\kappa\Linton{\gamma_{\mu}},
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\Linton{\gamma_{\mu}}=i\frac{\Kambe{\Gamma_{p}}}{\kappa}.
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Section
|
||||
D vs sigma
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
In-plane sums [Linton 2009, (4.5)], replacing
|
||||
\begin_inset Formula $n,m\rightarrow L,M$
|
||||
\end_inset
|
||||
|
||||
,
|
||||
\begin_inset Formula $k\rightarrow\kappa$
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
\lang english
|
||||
\begin_inset Formula
|
||||
\begin{eqnarray*}
|
||||
\sigma_{L}^{M(1)} & = & -\frac{i^{L+1}}{2\kappa^{2}\mathscr{A}}\left(-1\right)^{\left(L+M\right)/2}\sqrt{\left(2L+1\right)\left(L-M\right)!\left(L+M\right)!}\times\\
|
||||
& & \times\sum_{\vect K_{pq}\in\Lambda^{*}}^{'}\sum_{j=0}^{\left[\left(L-\left|M\right|/2\right)\right]}\frac{\left(-1\right)^{j}\left(\beta_{pq}/2\kappa\right)^{L-2j}e^{iM\phi_{\vect{\beta}_{pq}}}\Gamma_{j,pq}}{j!\left(\frac{1}{2}\left(L-M\right)-j\right)!\left(\frac{1}{2}\left(L+M\right)-j\right)!}\left(\frac{\gamma_{pq}}{2}\right)^{2j-1}
|
||||
\end{eqnarray*}
|
||||
|
||||
\end_inset
|
||||
|
||||
[Kambe II, (3.17)], replacing
|
||||
\lang finnish
|
||||
|
||||
\begin_inset Formula $n\rightarrow j$
|
||||
\end_inset
|
||||
|
||||
|
||||
\lang english
|
||||
,
|
||||
\lang finnish
|
||||
|
||||
\begin_inset Formula $A\rightarrow\mathscr{A}$
|
||||
\end_inset
|
||||
|
||||
,
|
||||
\begin_inset Formula $\vect K_{pt}\to\vect K_{p}$
|
||||
\end_inset
|
||||
|
||||
,
|
||||
\begin_inset Formula $\Gamma\left(\frac{1}{2}-j,e^{-i\pi}\Gamma_{p}^{2}\omega/2\right)\to\Gamma_{j,p}$
|
||||
\end_inset
|
||||
|
||||
and performing little typographic modifications
|
||||
\lang english
|
||||
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
D_{LM} & =-\frac{1}{\mathscr{A}\kappa}i^{\left|M\right|+1}2^{-L}\sqrt{\left(2L+1\right)\left(L+\left|M\right|\right)!\left(L-\left|M\right|\right)!}\times\\
|
||||
& \quad\times\sum_{p}e^{i\vect K_{p}\cdot\vect c_{ijt}}e^{-iM\phi_{K_{p}}}\sum_{j=0}^{\left(L-\left|M\right|\right)/2}\frac{\left(\Gamma_{p}/\kappa\right)^{2j-1}\left(K_{p}/\kappa\right)^{L-2j}\Gamma_{j,p}}{j!\left(\frac{1}{2}\left(L-\left|M\right|\right)-j\right)!\left(\frac{1}{2}\left(L+\left|M\right|\right)-j\right)!}
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
Using the relations between
|
||||
\begin_inset Formula $\Kambe{\Gamma_{p}}=-i\kappa\Linton{\gamma_{\mu}}$
|
||||
\end_inset
|
||||
|
||||
, we have (also, we replace the
|
||||
\begin_inset Formula $\mu$
|
||||
\end_inset
|
||||
|
||||
index with
|
||||
\begin_inset Formula $p$
|
||||
\end_inset
|
||||
|
||||
)
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
D_{LM} & =-\frac{1}{\mathscr{A}\kappa}i^{\left|M\right|+1}2^{-L}\sqrt{\left(2L+1\right)\left(L+\left|M\right|\right)!\left(L-\left|M\right|\right)!}\times\\
|
||||
& \quad\times\sum_{p}e^{i\vect K_{p}\cdot\vect c_{ijt}}e^{-iM\phi_{K_{p}}}\sum_{j=0}^{\left(L-\left|M\right|\right)/2}\frac{\left(-i\gamma_{p}\right)^{2j-1}\left(K_{p}/\kappa\right)^{L-2j}\Gamma_{j,p}}{j!\left(\frac{1}{2}\left(L-\left|M\right|\right)-j\right)!\left(\frac{1}{2}\left(L+\left|M\right|\right)-j\right)!}
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
and now, trying to make the exponents look the same as in Linton,
|
||||
\begin_inset Formula $2^{-1}2^{2j-L}2^{1-2j}=2^{-L}$
|
||||
\end_inset
|
||||
|
||||
(OK),
|
||||
\begin_inset Formula $K_{p}^{L-2j}=K_{p}^{L-2j}$
|
||||
\end_inset
|
||||
|
||||
(OK),
|
||||
\begin_inset Formula
|
||||
\begin{align*}
|
||||
D_{LM} & =-\frac{1}{2\kappa\mathscr{A}}i^{\left|M\right|+1}\sqrt{\left(2L+1\right)\left(L+\left|M\right|\right)!\left(L-\left|M\right|\right)!}\times\\
|
||||
& \quad\times\sum_{p}e^{i\vect K_{p}\cdot\vect c_{ij}}e^{-iM\phi_{K_{p}}}\sum_{j=0}^{\left(L-\left|M\right|\right)/2}\frac{\left(-i\right)^{2j-1}\left(K_{p}/2\kappa\right)^{L-2j}\Gamma_{j,p}}{j!\left(\frac{1}{2}\left(L-\left|M\right|\right)-j\right)!\left(\frac{1}{2}\left(L+\left|M\right|\right)-j\right)!}\left(\frac{\gamma_{p}}{2}\right)^{2j-1}
|
||||
\end{align*}
|
||||
|
||||
\end_inset
|
||||
|
||||
There are now these differences left:
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
|
||||
\lang english
|
||||
Additional
|
||||
\begin_inset Formula $\kappa$
|
||||
\end_inset
|
||||
|
||||
factor in
|
||||
\begin_inset Formula $D_{LM}$
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
|
||||
\lang english
|
||||
\begin_inset Formula $i^{L+1}\left(-1\right)^{\left(L+M\right)/2}\left(-1\right)^{j}$
|
||||
\end_inset
|
||||
|
||||
vs.
|
||||
|
||||
\begin_inset Formula $i^{\left|M\right|+1}\left(-i\right)^{2j-1}$
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
|
||||
\lang english
|
||||
Opposite phase in the angular part.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
|
||||
\lang english
|
||||
Plane wave factor in
|
||||
\begin_inset Formula $D_{LM}$
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
|
||||
\lang english
|
||||
Let's look at the
|
||||
\begin_inset Formula $i,-1$
|
||||
\end_inset
|
||||
|
||||
factors (note that
|
||||
\begin_inset Formula $L+M$
|
||||
\end_inset
|
||||
|
||||
is odd):
|
||||
\begin_inset Formula $\left(-i\right)^{2j}=\left(-1\right)^{j},$
|
||||
\end_inset
|
||||
|
||||
leaving
|
||||
\begin_inset Formula $i^{L+1}\left(-1\right)^{\left(L+M\right)/2}$
|
||||
\end_inset
|
||||
|
||||
vs.
|
||||
|
||||
\begin_inset Formula $i^{\left|M\right|+1}i$
|
||||
\end_inset
|
||||
|
||||
.
|
||||
So there is might be a phase difference due to different conventions, but
|
||||
it does not depend on
|
||||
\begin_inset Formula $j$
|
||||
\end_inset
|
||||
|
||||
, so one should be able to transplant the
|
||||
\begin_inset Formula $z\ne0$
|
||||
\end_inset
|
||||
|
||||
sum from Kambe without major problems.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Section
|
||||
Ewald parameter (integration limits)
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
\begin_inset Formula
|
||||
\[
|
||||
\Linton{\eta}=\sqrt{\frac{1}{2\Kambe{\omega}}}
|
||||
\]
|
||||
|
||||
\end_inset
|
||||
|
||||
(Based on comparison of some function arguments, not checked.)
|
||||
\end_layout
|
||||
|
||||
\end_body
|
||||
\end_document
|
|
@ -1,7 +1,9 @@
|
|||
#LyX 2.1 created this file. For more info see http://www.lyx.org/
|
||||
\lyxformat 474
|
||||
#LyX 2.3 created this file. For more info see http://www.lyx.org/
|
||||
\lyxformat 544
|
||||
\begin_document
|
||||
\begin_header
|
||||
\save_transient_properties true
|
||||
\origin unavailable
|
||||
\textclass report
|
||||
\begin_preamble
|
||||
%\renewcommand*{\chapterheadstartvskip}{\vspace*{1cm}}
|
||||
|
@ -13,16 +15,18 @@
|
|||
\language_package default
|
||||
\inputencoding auto
|
||||
\fontencoding global
|
||||
\font_roman TeX Gyre Pagella
|
||||
\font_sans default
|
||||
\font_typewriter default
|
||||
\font_math auto
|
||||
\font_roman "default" "TeX Gyre Pagella"
|
||||
\font_sans "default" "default"
|
||||
\font_typewriter "default" "default"
|
||||
\font_math "auto" "auto"
|
||||
\font_default_family default
|
||||
\use_non_tex_fonts true
|
||||
\font_sc false
|
||||
\font_osf true
|
||||
\font_sf_scale 100
|
||||
\font_tt_scale 100
|
||||
\font_sf_scale 100 100
|
||||
\font_tt_scale 100 100
|
||||
\use_microtype false
|
||||
\use_dash_ligatures false
|
||||
\graphics default
|
||||
\default_output_format pdf4
|
||||
\output_sync 0
|
||||
|
@ -63,6 +67,7 @@
|
|||
\suppress_date false
|
||||
\justification true
|
||||
\use_refstyle 1
|
||||
\use_minted 0
|
||||
\index Index
|
||||
\shortcut idx
|
||||
\color #008000
|
||||
|
@ -75,7 +80,10 @@
|
|||
\tocdepth 3
|
||||
\paragraph_separation indent
|
||||
\paragraph_indentation default
|
||||
\quotes_language swedish
|
||||
\is_math_indent 0
|
||||
\math_numbering_side default
|
||||
\quotes_style swedish
|
||||
\dynamic_quotes 0
|
||||
\papercolumns 1
|
||||
\papersides 1
|
||||
\paperpagestyle default
|
||||
|
@ -102,7 +110,7 @@
|
|||
\end_layout
|
||||
|
||||
\begin_layout Title
|
||||
Electromagnetic multiple scattering, spherical waves and ****
|
||||
Electromagnetic multiple scattering, spherical waves and conventions
|
||||
\end_layout
|
||||
|
||||
\begin_layout Author
|
||||
|
@ -244,7 +252,7 @@ Pi and tau
|
|||
Xu
|
||||
\begin_inset CommandInset label
|
||||
LatexCommand label
|
||||
name "sub:Xu pitau"
|
||||
name "subsec:Xu pitau"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -373,7 +381,7 @@ The limiting expressions are obtained simply by multiplying the expressions
|
|||
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand ref
|
||||
reference "sub:Xu pitau"
|
||||
reference "subsec:Xu pitau"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -462,6 +470,7 @@ Jackson
|
|||
LatexCommand cite
|
||||
after "(9.101)"
|
||||
key "jackson_classical_1998"
|
||||
literal "true"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -478,6 +487,7 @@ where
|
|||
LatexCommand cite
|
||||
after "(9.119)"
|
||||
key "jackson_classical_1998"
|
||||
literal "true"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -499,6 +509,7 @@ Normalisation
|
|||
LatexCommand cite
|
||||
after "(9.120)"
|
||||
key "jackson_classical_1998"
|
||||
literal "true"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -519,6 +530,7 @@ Local sum rule
|
|||
LatexCommand cite
|
||||
after "(9.153)"
|
||||
key "jackson_classical_1998"
|
||||
literal "true"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -793,6 +805,7 @@ As in
|
|||
LatexCommand cite
|
||||
after "eq. (36)"
|
||||
key "xu_calculation_1996"
|
||||
literal "true"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -816,6 +829,7 @@ where CS is
|
|||
LatexCommand cite
|
||||
after "eq. (81)"
|
||||
key "xu_calculation_1996"
|
||||
literal "true"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -826,7 +840,7 @@ key "xu_calculation_1996"
|
|||
Relation between Kristensson and Taylor
|
||||
\begin_inset CommandInset label
|
||||
LatexCommand label
|
||||
name "sub:Kristensson-v-Taylor"
|
||||
name "subsec:Kristensson-v-Taylor"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -961,7 +975,7 @@ In this section I summarize the formulae for power
|
|||
Kristensson
|
||||
\begin_inset CommandInset label
|
||||
LatexCommand label
|
||||
name "sub:Radiated enenergy-Kristensson"
|
||||
name "subsec:Radiated enenergy-Kristensson"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -1022,7 +1036,7 @@ Here I derive the radiated power in Taylor's convention by applying the
|
|||
relations from subsection
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand ref
|
||||
reference "sub:Kristensson-v-Taylor"
|
||||
reference "subsec:Kristensson-v-Taylor"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -1030,7 +1044,7 @@ reference "sub:Kristensson-v-Taylor"
|
|||
|
||||
\begin_inset CommandInset ref
|
||||
LatexCommand ref
|
||||
reference "sub:Radiated enenergy-Kristensson"
|
||||
reference "subsec:Radiated enenergy-Kristensson"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -1110,6 +1124,7 @@ Jackson
|
|||
LatexCommand cite
|
||||
after "(9.155)"
|
||||
key "jackson_classical_1998"
|
||||
literal "true"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -1138,6 +1153,7 @@ TODO start from
|
|||
LatexCommand cite
|
||||
after "(A7)"
|
||||
key "pustovit_plasmon-mediated_2010"
|
||||
literal "true"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -1317,6 +1333,7 @@ TODO start from
|
|||
LatexCommand cite
|
||||
after "(A11)"
|
||||
key "pustovit_plasmon-mediated_2010"
|
||||
literal "true"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -1479,6 +1496,7 @@ Cruzan's formulation, Xu's normalisation
|
|||
LatexCommand cite
|
||||
after "(59)"
|
||||
key "xu_efficient_1998"
|
||||
literal "true"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -1495,6 +1513,7 @@ where
|
|||
LatexCommand cite
|
||||
after "(28,5,60,61)"
|
||||
key "xu_efficient_1998"
|
||||
literal "true"
|
||||
|
||||
\end_inset
|
||||
|
|
@ -7,25 +7,35 @@ find_package(LAPACK REQUIRED)
|
|||
# and other not very relevant warnings
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-int-in-bool-context -Wno-comment")
|
||||
|
||||
# version file
|
||||
include(GetGitRevisionDescription)
|
||||
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/version.c.in" "${CMAKE_CURRENT_BINARY_DIR}/version.c" @ONLY)
|
||||
list(APPEND SOURCES "${CMAKE_CURRENT_BINARY_DIR}/version.c" version.h)
|
||||
|
||||
#includes
|
||||
set (DIRS ${GSL_INCLUDE_DIRS} ${GSLCBLAS_INCLUDE_DIRS})
|
||||
include_directories(${DIRS})
|
||||
|
||||
|
||||
|
||||
add_library (qpms SHARED translations.c tmatrices.c vecprint.c vswf.c wigner.c ewald.c
|
||||
ewaldsf.c pointgroups.c latticegens.c
|
||||
lattices2d.c gaunt.c error.c legendre.c symmetries.c vecprint.c
|
||||
bessel.c own_zgemm.c parsing.c scatsystem.c materials.c drudeparam_data.c
|
||||
lll.c beyn.c trivialgroup.c
|
||||
lll.c beyn.c trivialgroup.c version.c
|
||||
)
|
||||
use_c99()
|
||||
|
||||
set(LIBS ${LIBS} ${GSL_LIBRARIES} ${GSLCBLAS_LIBRARIES})
|
||||
|
||||
|
||||
target_link_libraries (qpms
|
||||
gsl
|
||||
lapack
|
||||
blas
|
||||
amos
|
||||
${GSL_LIBRARIES}
|
||||
${LAPACK_LIBRARIES}
|
||||
${BLAS_LIBRARIES}
|
||||
${QPMS_AMOSLIB}
|
||||
Faddeeva
|
||||
)
|
||||
target_include_directories (qpms PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
from pkg_resources import get_distribution
|
||||
__version__ = get_distribution('qpms').version
|
||||
|
||||
import os as __os
|
||||
from sys import platform as __platform
|
||||
|
@ -7,7 +5,7 @@ from sys import platform as __platform
|
|||
import warnings as __warnings
|
||||
|
||||
try:
|
||||
from .qpms_c import PointGroup, FinitePointGroup, FinitePointGroupElement, Particle, scatsystem_set_nthreads, ScatteringSystem, ScatteringMatrix, pitau, set_gsl_pythonic_error_handling, pgsl_ignore_error, gamma_inc, lll_reduce
|
||||
from .qpms_c import PointGroup, FinitePointGroup, FinitePointGroupElement, Particle, scatsystem_set_nthreads, ScatteringSystem, ScatteringMatrix, pitau, set_gsl_pythonic_error_handling, pgsl_ignore_error, gamma_inc, lll_reduce, qpms_library_version
|
||||
except ImportError as ex:
|
||||
if __platform == "linux" or __platform == "linux2":
|
||||
if 'LD_LIBRARY_PATH' not in __os.environ.keys():
|
||||
|
@ -24,7 +22,12 @@ from .cymaterials import MaterialInterpolator, EpsMu, LorentzDrudeModel, lorentz
|
|||
from .cycommon import dbgmsg_enable, dbgmsg_disable, dbgmsg_active, BesselType, VSWFType
|
||||
from .cywaves import vswf_single
|
||||
|
||||
from .qpms_p import * # maybe don't import automatically in the future (adds around 0.5 s delay)
|
||||
def __version__():
|
||||
from pkg_resources import get_distribution
|
||||
librev = qpms_library_version()
|
||||
return get_distribution('qpms').version + (("lr:"+librev) if librev else "")
|
||||
|
||||
#from .qpms_p import * # don't import automatically (adds around 0.5 s delay and depends on scipy)
|
||||
from .constants import *
|
||||
|
||||
# legacy code which brutally slows down the whole package init:
|
||||
|
|
493
qpms/argproc.py
493
qpms/argproc.py
|
@ -1,9 +1,17 @@
|
|||
'''
|
||||
Common snippets for argument processing in command line scripts; legacy scripts use scripts_common.py instead.
|
||||
Common snippets for argument processing in command line scripts.
|
||||
'''
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
def flatten(S):
|
||||
if S == []:
|
||||
return S
|
||||
if isinstance(S[0], list):
|
||||
return flatten(S[0]) + flatten(S[1:])
|
||||
return S[:1] + flatten(S[1:])
|
||||
|
||||
def make_action_sharedlist(opname, listname):
|
||||
class opAction(argparse.Action):
|
||||
|
@ -13,6 +21,40 @@ def make_action_sharedlist(opname, listname):
|
|||
getattr(args, listname).append((opname, values))
|
||||
return opAction
|
||||
|
||||
def make_dict_action(argtype=None, postaction='store', first_is_key=True):
|
||||
class DictAction(argparse.Action):
|
||||
#def __init__(self, option_strings, dest, nargs=None, **kwargs):
|
||||
# if nargs is not None:
|
||||
# raise ValueError("nargs not allowed")
|
||||
# super(DictAction, self).__init__(option_strings, dest, **kwargs)
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
if first_is_key: # For the labeled versions
|
||||
key = values[0]
|
||||
vals = values[1:]
|
||||
else: # For the default values
|
||||
key = None
|
||||
vals = values
|
||||
if argtype is not None:
|
||||
if (first_is_key and self.nargs == 2) or (not first_is_key and self.nargs == 1):
|
||||
vals = argtype(vals[0]) # avoid having lists in this case
|
||||
else:
|
||||
vals = [argtype(val) for val in vals]
|
||||
ledict = getattr(namespace, self.dest, {})
|
||||
if ledict is None:
|
||||
ledict = {}
|
||||
if postaction=='store':
|
||||
ledict[key] = vals
|
||||
elif postaction=='append':
|
||||
lelist = ledict.get(key, [])
|
||||
lelist.append(vals)
|
||||
ledict[key] = lelist
|
||||
setattr(namespace, self.dest, ledict)
|
||||
return DictAction
|
||||
|
||||
|
||||
class ArgumentProcessingError(Exception):
|
||||
pass
|
||||
|
||||
class AppendTupleAction(argparse.Action):
|
||||
''' A variation on the 'append' builtin action from argparse, but uses tuples for the internal groupings instead of lists '''
|
||||
def __call__(self, parser, args, values, option_string=None):
|
||||
|
@ -20,51 +62,299 @@ class AppendTupleAction(argparse.Action):
|
|||
setattr(args, self.dest, list())
|
||||
getattr(args, self.dest).append(tuple(values))
|
||||
|
||||
def float_range(string):
|
||||
"""Tries to parse a string either as one individual float value
|
||||
or one of the following patterns:
|
||||
|
||||
first:last:increment
|
||||
first:last|steps
|
||||
first:last
|
||||
|
||||
(The last one is equivalent to first:last|50.)
|
||||
Returns either float or numpy array.
|
||||
"""
|
||||
try:
|
||||
res = float(string)
|
||||
return res
|
||||
except ValueError:
|
||||
import re
|
||||
steps = None
|
||||
match = re.match(r's?([^:]+):([^|]+)\|(.+)', string)
|
||||
if match:
|
||||
steps = int(match.group(3))
|
||||
else:
|
||||
match = re.match(r's?([^:]+):([^:]+):(.+)', string)
|
||||
if match:
|
||||
increment = float(match.group(3))
|
||||
else:
|
||||
match = re.match(r's?([^:]+):(.+)', string)
|
||||
if match:
|
||||
steps = 50
|
||||
else:
|
||||
argparse.ArgumentTypeError('Invalid float/sequence format: "%s"' % string)
|
||||
first = float(match.group(1))
|
||||
last = float(match.group(2))
|
||||
import numpy as np
|
||||
if steps is not None:
|
||||
return np.linspace(first, last, num=steps)
|
||||
else:
|
||||
return np.arange(first, last, increment)
|
||||
|
||||
def int_or_None(string):
|
||||
"""Tries to parse a string either as an int or None (if it contains only whitespaces)"""
|
||||
try:
|
||||
return int(string)
|
||||
except ValueError as ve:
|
||||
if string.strip() == '':
|
||||
return None
|
||||
else:
|
||||
raise ve
|
||||
|
||||
def sslice(string):
|
||||
"""Tries to parse a string either as one individual int value
|
||||
or one of the following patterns:
|
||||
|
||||
first:last:increment
|
||||
first:last
|
||||
|
||||
first, last and increment must be parseable as ints
|
||||
or be empty (then
|
||||
|
||||
In each case, 's' letter can be prepended to the whole string to avoid
|
||||
argparse interpreting this as a new option (if the argument contains
|
||||
'-' or '+').
|
||||
|
||||
Returns either int or slice containing ints or Nones.
|
||||
"""
|
||||
if string[0] == 's':
|
||||
string = string[1:]
|
||||
try:
|
||||
res = int(string)
|
||||
return res
|
||||
except ValueError:
|
||||
import re
|
||||
match = re.match(r'([^:]*):([^:]*):(.*)', string)
|
||||
if match:
|
||||
step = int_or_None(match.group(3))
|
||||
else:
|
||||
match = re.match(r'([^:]*):(.*)', string)
|
||||
if match:
|
||||
step = None
|
||||
else:
|
||||
argparse.ArgumentTypeError('Invalid int/slice format: "%s"' % string)
|
||||
start = int_or_None(match.group(1))
|
||||
stop = int_or_None(match.group(2))
|
||||
return slice(start, stop, step)
|
||||
|
||||
def sfloat(string):
|
||||
'''Tries to match a float, or a float with prepended 's'
|
||||
|
||||
Used as a workaraound for argparse's negative number matcher, which does not recognize
|
||||
scientific notation.
|
||||
'''
|
||||
try:
|
||||
res = float(string)
|
||||
except ValueError as exc:
|
||||
if string[0] == 's':
|
||||
res = float(string[1:])
|
||||
else: raise exc
|
||||
return res
|
||||
|
||||
def sint(string):
|
||||
'''Tries to match an int, or an int with prepended 's'
|
||||
|
||||
Used as a workaraound for argparse's negative number matcher if '+' is used as a
|
||||
prefix
|
||||
'''
|
||||
try:
|
||||
res = int(string)
|
||||
except ValueError as exc:
|
||||
if string[0] == 's':
|
||||
res = int(string[1:])
|
||||
else: raise exc
|
||||
return res
|
||||
|
||||
def material_spec(string):
|
||||
"""Tries to parse a string as a material specification, i.e. a
|
||||
real or complex number or one of the string in built-in Lorentz-Drude models.
|
||||
|
||||
Tries to interpret the string as 1) float, 2) complex, 3) Lorentz-Drude key.
|
||||
Raises argparse.ArgumentTypeError on failure.
|
||||
"""
|
||||
from .cymaterials import lorentz_drude
|
||||
if string in lorentz_drude.keys():
|
||||
return string
|
||||
else:
|
||||
try: lemat = float(string)
|
||||
except ValueError:
|
||||
try: lemat = complex(string)
|
||||
except ValueError as ve:
|
||||
raise argparse.ArgumentTypeError("Material specification must be a supported material name %s, or a number" % (str(lorentz_drude.keys()),)) from ve
|
||||
return lemat
|
||||
|
||||
class ArgParser:
|
||||
''' Common argument parsing engine for QPMS python CLI scripts. '''
|
||||
|
||||
def __add_planewave_argparse_group(ap):
|
||||
pwgrp = ap.add_argument_group('Incident wave specification', """
|
||||
Incident wave direction is given in terms of ISO polar and azimuthal angles θ, φ,
|
||||
which translate into cartesian coordinates as r̂ = (x, y, z) = (sin(θ) cos(φ), sin(θ) sin(φ), cos(θ)).
|
||||
|
||||
Wave polarisation is given in terms of parameters ψ, χ, where ψ is the angle between a polarisation
|
||||
ellipse axis and meridian tangent θ̂, and tg χ determines axes ratio;
|
||||
the electric field in the origin is then
|
||||
|
||||
E⃗ = cos(χ) (cos(ψ) θ̂ + sin(ψ) φ̂) + i sin(χ) (sin(ψ) θ̂ + cos(ψ) φ̂).
|
||||
|
||||
All the angles are given as multiples of π/2.
|
||||
""" # TODO EXAMPLES
|
||||
)
|
||||
pwgrp.add_argument("-φ", "--phi", type=float, default=0,
|
||||
help='Incident wave asimuth in multiples of π/2.')
|
||||
pwgrp.add_argument("-θ", "--theta", type=float_range, default=0,
|
||||
help='Incident wave polar angle in multiples of π/2. This might be a sequence in format FIRST:LAST:INCREMENT.')
|
||||
pwgrp.add_argument("-ψ", "--psi", type=float, default=0,
|
||||
help='Angle between polarisation ellipse axis and meridian tangent θ̂ in multiples of π/2.')
|
||||
pwgrp.add_argument("-χ", "--chi", type=float, default=0,
|
||||
help='Polarisation parameter χ in multiples of π/2. 0 for linear, 0.5 for circular pol.')
|
||||
|
||||
def __add_manyparticle_argparse_group(ap):
|
||||
mpgrp = ap.add_argument_group('Many particle specification', "TODO DOC")
|
||||
mpgrp.add_argument("-p", "--position", nargs='+', action=make_dict_action(argtype=sfloat, postaction='append',
|
||||
first_is_key=False), help="Particle positions, cartesion coordinates (default particle properties)")
|
||||
mpgrp.add_argument("+p", "++position", nargs='+', action=make_dict_action(argtype=sfloat, postaction='append',
|
||||
first_is_key=True), help="Particle positions, cartesian coordinates (labeled)")
|
||||
mpgrp.add_argument("-L", "--lMax", nargs=1, default={},
|
||||
action=make_dict_action(argtype=int, postaction='store', first_is_key=False,),
|
||||
help="Cutoff multipole degree (default)")
|
||||
mpgrp.add_argument("+L", "++lMax", nargs=2,
|
||||
action=make_dict_action(argtype=int, postaction='store', first_is_key=True,),
|
||||
help="Cutoff multipole degree (labeled)")
|
||||
mpgrp.add_argument("-m", "--material", nargs=1, default={},
|
||||
action=make_dict_action(argtype=material_spec, postaction='store', first_is_key=False,),
|
||||
help='particle material (Au, Ag, ... for Lorentz-Drude or number for constant refractive index) (default)')
|
||||
mpgrp.add_argument("+m", "++material", nargs=2,
|
||||
action=make_dict_action(argtype=material_spec, postaction='store', first_is_key=True,),
|
||||
help='particle material (Au, Ag, ... for Lorentz-Drude or number for constant refractive index) (labeled)')
|
||||
mpgrp.add_argument("-r", "--radius", nargs=1, default={},
|
||||
action=make_dict_action(argtype=float, postaction='store', first_is_key=False,),
|
||||
help='particle radius (sphere or cylinder; default)')
|
||||
mpgrp.add_argument("+r", "++radius", nargs=2,
|
||||
action=make_dict_action(argtype=float, postaction='store', first_is_key=True,),
|
||||
help='particle radius (sphere or cylinder; labeled)')
|
||||
mpgrp.add_argument("-H", "--height", nargs=1, default={},
|
||||
action=make_dict_action(argtype=float, postaction='store', first_is_key=False,),
|
||||
help='particle radius (cylinder; default)')
|
||||
mpgrp.add_argument("+H", "++height", nargs=2,
|
||||
action=make_dict_action(argtype=float, postaction='store', first_is_key=True,),
|
||||
help='particle radius (cylinder; labeled)')
|
||||
|
||||
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')),
|
||||
'single_frequency_eV': lambda ap: ap.add_argument("-f", "--eV", type=float, required=True, help='radiation angular frequency in eV'),
|
||||
'single_material': lambda ap: ap.add_argument("-m", "--material", help='particle material (Au, Ag, ... for Lorentz-Drude or number for constant refractive index)', default='Au', required=True),
|
||||
'multiple_frequency_eV_optional': lambda ap: ap.add_argument("-f", "--eV", type=float, nargs='*', help='radiation angular frequency in eV (additional)'),
|
||||
'seq_frequency_eV': lambda ap: ap.add_argument("-F", "--eV-seq", type=float, nargs=3, required=True, help='uniform radiation angular frequency sequence in eV', metavar=('FIRST', 'INCREMENT', 'LAST')),
|
||||
'real_frequencies_eV_ng': lambda ap: ap.add_argument("-f", "--eV", type=float_range, nargs=1, action='append', required=True, help='Angular frequency (or angular frequency range) in eV'), # nargs='+', action='extend' would be better, but action='extend' requires python>=3.8
|
||||
'single_material': lambda ap: ap.add_argument("-m", "--material", help='particle material (Au, Ag, ... for Lorentz-Drude or number for constant refractive index)', type=material_spec, required=True),
|
||||
'single_radius': lambda ap: ap.add_argument("-r", "--radius", type=float, required=True, help='particle radius (sphere or cylinder)'),
|
||||
'single_height': lambda ap: ap.add_argument("-H", "--height", type=float, help='cylindrical particle height; if not provided, particle is assumed to be spherical'),
|
||||
'single_kvec2': lambda ap: ap.add_argument("-k", '--kx-lim', nargs=2, type=float, required=True, help='k vector', metavar=('KX_MIN', 'KX_MAX')),
|
||||
'single_kvec2': lambda ap: ap.add_argument("-k", '--kx-lim', nargs=2, type=sfloat, required=True, help='k vector', metavar=('KX_MIN', 'KX_MAX')),
|
||||
'kpi': lambda ap: 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)"),
|
||||
'bg_refractive_index': lambda ap: ap.add_argument("-n", "--refractive-index", type=float, default=1.52, help='background medium 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)"),
|
||||
'single_lMax': lambda ap: ap.add_argument("-L", "--lMax", type=int, required=True, default=3, help='multipole degree cutoff'),
|
||||
'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)"),
|
||||
'plot_do': lambda ap: ap.add_argument("-P", "--plot", action='store_true', help="if -p not given, plot to a default path"),
|
||||
'lattice2d_basis': lambda ap: ap.add_argument("-b", "--basis-vector", action=AppendTupleAction, help="basis vector in xy-cartesian coordinates (two required)", dest='basis_vectors', metavar=('X', 'Y')),
|
||||
'lattice2d_basis': lambda ap: ap.add_argument("-b", "--basis-vector", nargs='+', action=AppendTupleAction, help="basis vector in xy-cartesian coordinates (two required)", required=True, type=sfloat, dest='basis_vectors', metavar=('X', 'Y')),
|
||||
'planewave_pol_angles': __add_planewave_argparse_group,
|
||||
'multi_particle': __add_manyparticle_argparse_group,
|
||||
}
|
||||
|
||||
feature_sets_available = { # name : (description, dependencies, atoms not in other dependencies, methods called after parsing)
|
||||
'background': ("Background medium definition (currently only constant epsilon supported)", (), ('bg_refractive_index',), ('_eval_background_epsmu',)),
|
||||
'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_lMax': ("Single particle lMax definition", (), ('single_lMax',), ()),
|
||||
'single_omega': ("Single angular frequency", (), ('single_frequency_eV',), ('_eval_single_omega',)),
|
||||
'lattice2d': ("Specification of a generic 2d lattice (spanned by the x,y axes)", (), ('lattice2d_basis',), ('_eval_lattice2d',)),
|
||||
'rectlattice2d': ("Specification of a rectangular 2d lattice; conflicts with lattice2d", (), ('rectlattice2d_periods',), ('_eval_rectlattice2d',)),
|
||||
'rectlattice2d_finite': ("Specification of a rectangular 2d lattice; conflicts with lattice2d", ('rectlattice2d',), ('rectlattice2d_counts',), ()),
|
||||
feature_sets_available = { # name : (description, dependencies, atoms not in other dependencies, methods called after parsing, "virtual" features provided)
|
||||
'const_real_background': ("Background medium with constant real refractive index", (), ('bg_real_refractive_index',), ('_eval_const_background_epsmu',), ('background', 'background_analytical')),
|
||||
'background' : ("Most general background medium specification currently supported", ('background_analytical',), (), (), ()),
|
||||
'background_analytical' : ("Background medium model holomorphic for 'reasonably large' complex frequency areas", (), ('bg_analytical',), ('_eval_analytical_background_epsmugen',), ('background',)),
|
||||
'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_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',), ()),
|
||||
'lattice2d': ("Specification of a generic 2d lattice (spanned by the x,y axes)", (), ('lattice2d_basis',), ('_eval_lattice2d',), ()),
|
||||
'rectlattice2d': ("Specification of a rectangular 2d lattice; conflicts with lattice2d", (), ('rectlattice2d_periods',), ('_eval_rectlattice2d',), ()),
|
||||
'rectlattice2d_finite': ("Specification of a rectangular 2d lattice; conflicts with lattice2d", ('rectlattice2d',), ('rectlattice2d_counts',), (), ()),
|
||||
'planewave': ("Specification of a normalised plane wave (typically used for scattering) with a full polarisation state", (), ('planewave_pol_angles',), ("_process_planewave_angles",), ()),
|
||||
}
|
||||
|
||||
|
||||
def __init__(self, features=[]):
|
||||
self.ap = argparse.ArgumentParser()
|
||||
prefix_chars = '+-' if 'multi_particle' in features else '-'
|
||||
self.ap = argparse.ArgumentParser(prefix_chars=prefix_chars)
|
||||
self.features_enabled = set()
|
||||
self.call_at_parse_list = []
|
||||
self.parsed = False
|
||||
for feat in features:
|
||||
self.add_feature(feat)
|
||||
self._emg_register = {} # EpsMuGenerator dictionary to avoid recreating equivalent instances; filled by _add_emg()
|
||||
self._tmg_register = {} # TMatrixGenerator dictionary to avoid recreating equivalent instances; filled by _add_tmg()
|
||||
self._bspec_register = {} # Dictionary of used BaseSpecs to keep the equivalent instances unique; filled by _add_bspec()
|
||||
|
||||
def _add_emg(self, emgspec):
|
||||
"""Looks up whether if an EpsMuGenerator from given material_spec has been already registered, and if not, creates a new one"""
|
||||
from .cymaterials import EpsMu, EpsMuGenerator, lorentz_drude
|
||||
if emgspec in self._emg_register.keys():
|
||||
return self._emg_register[emgspec]
|
||||
else:
|
||||
if isinstance(emgspec, (float, complex)):
|
||||
emg = EpsMuGenerator(EpsMu(emgspec**2))
|
||||
else:
|
||||
emg = EpsMuGenerator(lorentz_drude[emgspec])
|
||||
self._emg_register[emgspec] = emg
|
||||
return emg
|
||||
|
||||
def _add_tmg(self, tmgspec):
|
||||
"""Looks up whether if a T-matrix from given T-matrix specification tuple has been already registered, and if not, creates a new one
|
||||
|
||||
T-matrix specification shall be of the form
|
||||
(bg_material_spec, fg_material_spec, shape_spec) where shape_spec is
|
||||
(radius, height, lMax_extend)
|
||||
"""
|
||||
if tmgspec in self._tmg_register.keys():
|
||||
return self._tmg_register[tmgspec]
|
||||
else:
|
||||
from .cytmatrices import TMatrixGenerator
|
||||
bgspec, fgspec, (radius, height, lMax_extend) = tmgspec
|
||||
bg = self._add_emg(bgspec)
|
||||
fg = self._add_emg(fgspec)
|
||||
if height is None:
|
||||
tmgen = TMatrixGenerator.sphere(bg, fg, radius)
|
||||
else:
|
||||
tmgen = TMatrixGenerator.cylinder(bg, fg, radius, height, lMax_extend=lMax_extend)
|
||||
self._tmg_register[tmgspec] = tmgen
|
||||
return tmgen
|
||||
|
||||
def _add_bspec(self, key):
|
||||
if key in self._bspec_register.keys():
|
||||
return self._bspec_register[key]
|
||||
else:
|
||||
from .cybspec import BaseSpec
|
||||
if isinstance(key, BaseSpec):
|
||||
bspec = key
|
||||
elif isinstance(key, int):
|
||||
bspec = self._add_bspec(BaseSpec(lMax=key))
|
||||
else: raise TypeError("Can't register this as a BaseSpec")
|
||||
self._bspec_register[key] = bspec
|
||||
return bspec
|
||||
|
||||
def add_feature(self, feat):
|
||||
if feat not in self.features_enabled:
|
||||
if feat not in ArgParser.feature_sets_available:
|
||||
raise ValueError("Unknown ArgParser feature: %s" % feat)
|
||||
#resolve dependencies
|
||||
_, deps, atoms, atparse = ArgParser.feature_sets_available[feat]
|
||||
_, deps, atoms, atparse, provides_virtual = ArgParser.feature_sets_available[feat]
|
||||
for dep in deps:
|
||||
self.add_feature(dep)
|
||||
for atom in atoms: # maybe check whether that atom has already been added sometimes in the future?
|
||||
|
@ -72,16 +362,26 @@ class ArgParser:
|
|||
for methodname in atparse:
|
||||
self.call_at_parse_list.append(methodname)
|
||||
self.features_enabled.add(feat)
|
||||
for feat_virt in provides_virtual:
|
||||
self.features_enabled.add(feat_virt)
|
||||
|
||||
def add_argument(self, *args, **kwargs):
|
||||
'''Add a custom argument directly to the standard library ArgParser object'''
|
||||
self.ap.add_argument(*args, **kwargs)
|
||||
return self.ap.add_argument(*args, **kwargs)
|
||||
|
||||
def add_argument_group(self, *args, **kwargs):
|
||||
'''Add a custom argument group directly to the standard library ArgParser object'''
|
||||
return self.ap.add_argument_group(*args, **kwargs)
|
||||
|
||||
def parse_args(self, process_data = True, *args, **kwargs):
|
||||
self.args = self.ap.parse_args(*args, **kwargs)
|
||||
if process_data:
|
||||
for method in self.call_at_parse_list:
|
||||
getattr(self, method)()
|
||||
try:
|
||||
getattr(self, method)()
|
||||
except ArgumentProcessingError:
|
||||
err = sys.exc_info()[1]
|
||||
self.ap.error(str(err))
|
||||
return self.args
|
||||
|
||||
def __getattr__(self, name):
|
||||
|
@ -90,42 +390,66 @@ class ArgParser:
|
|||
|
||||
# Methods to initialise the related data structures:
|
||||
|
||||
def _eval_background_epsmu(self): # feature: background
|
||||
from .cymaterials import EpsMu, EpsMuGenerator
|
||||
self.background_epsmu = EpsMu(self.args.refractive_index**2)
|
||||
self.background_emg = EpsMuGenerator(self.background_epsmu)
|
||||
def _eval_const_background_epsmu(self): # feature: const_real_background
|
||||
self.args.background = self.args.refractive_index
|
||||
self._eval_analytical_background_epsmugen()
|
||||
|
||||
def _eval_analytical_background_epsmugen(self): # feature: background_analytical
|
||||
a = self.args
|
||||
from .cymaterials import EpsMu
|
||||
if isinstance(a.background, (float, complex)):
|
||||
self.background_epsmu = EpsMu(a.background**2)
|
||||
self.background_emg = self._add_emg(a.background)
|
||||
|
||||
def _eval_single_tmgen(self): # feature: single_particle
|
||||
a = self.args
|
||||
from .cymaterials import EpsMuGenerator, lorentz_drude
|
||||
from .cytmatrices import TMatrixGenerator
|
||||
if a.material in lorentz_drude.keys():
|
||||
self.foreground_emg = EpsMuGenerator(lorentz_drude[a.material])
|
||||
else:
|
||||
try: lemat = float(a.material)
|
||||
except ValueError:
|
||||
try: lemat = complex(a.material)
|
||||
except ValueError as ve:
|
||||
raise ValueError("--material must be either a label such as 'Ag', 'Au', or a number") from ve
|
||||
a.material = lemat
|
||||
self.foreground_emg = EpsMuGenerator(EpsMu(a.material**2))
|
||||
|
||||
if a.height is None:
|
||||
self.tmgen = TMatrixGenerator.sphere(self.background_emg, self.foreground_emg, a.radius)
|
||||
else:
|
||||
self.tmgen = TMatrixGenerator.cylinder(self.background_emg, self.foreground_emg, a.radius, a.height, lMax_extend = a.lMax_extend)
|
||||
self.foreground_emg = self._add_emg(a.material)
|
||||
self.tmgen = self._add_tmg((a.background, a.material, (a.radius, a.height, a.lMax_extend)))
|
||||
self.bspec = self._add_bspec(a.lMax)
|
||||
|
||||
def _eval_single_omega(self): # feature: single_omega
|
||||
from .constants import eV, hbar
|
||||
self.omega = self.args.eV * eV / hbar
|
||||
|
||||
def _eval_omega_seq(self): # feature: omega_seq
|
||||
import numpy as np
|
||||
from .constants import eV, hbar
|
||||
start, step, stop = self.args.eV_seq
|
||||
self.omegas = np.arange(start, stop, step)
|
||||
if self.args.eV:
|
||||
self.omegas = np.concatenate((self.omegas, np.array(self.args.eV)))
|
||||
self.omegas.sort()
|
||||
self.omegas *= eV/hbar
|
||||
|
||||
def _eval_omega_seq_real_ng(self): # feature: omega_seq_real_ng
|
||||
import numpy as np
|
||||
from .constants import eV, hbar
|
||||
eh = eV / hbar
|
||||
self.omegas = [omega_eV * eh for omega_eV in flatten(self.args.eV)]
|
||||
self.omega_max = max(om if isinstance(om, float) else max(om) for om in self.omegas)
|
||||
self.omega_min = min(om if isinstance(om, float) else min(om) for om in self.omegas)
|
||||
self.omega_singles = [om for om in self.omegas if isinstance(om, float)]
|
||||
self.omega_ranges = [om for om in self.omegas if not isinstance(om, float)]
|
||||
self.omega_descr = ("%geV" % (self.omega_max / eh)) if (self.omega_max == self.omega_min) else (
|
||||
"%g–%geV" % (self.omega_min / eh, self.omega_max / eh))
|
||||
self.allomegas = []
|
||||
for om in self.omegas:
|
||||
if isinstance(om, float):
|
||||
self.allomegas.append(om)
|
||||
else:
|
||||
self.allomegas.extend(om)
|
||||
self.allomegas = np.unique(self.allomegas)
|
||||
|
||||
|
||||
def _eval_lattice2d(self): # feature: lattice2d
|
||||
l = len(self.args.basis_vectors)
|
||||
if l != 2: raise ValueError('Two basis vectors must be specified (have %d)' % l)
|
||||
from .qpms_c import lll_reduce
|
||||
self.direct_basis = lll_reduce(self.args.basis_vector, delta=1.)
|
||||
self.direct_basis = lll_reduce(self.args.basis_vectors, delta=1.)
|
||||
import numpy as np
|
||||
self.reciprocal_basis1 = np.linalg.inv(self.direct_basis)
|
||||
self.reciprocal_basis1 = np.linalg.inv(self.direct_basis.T)
|
||||
self.reciprocal_basis2pi = 2 * np.pi * self.reciprocal_basis1
|
||||
|
||||
def _eval_rectlattice2d(self): # feature: rectlattice2d
|
||||
|
@ -141,6 +465,97 @@ class ArgParser:
|
|||
import numpy as np
|
||||
a.basis_vectors = [(a.period[0], 0.), (0., a.period[1])]
|
||||
self.direct_basis = np.array(a.basis_vectors)
|
||||
self.reciprocal_basis1 = np.linalg.inv(self.direct_basis)
|
||||
self.reciprocal_basis1 = np.linalg.inv(self.direct_basis.T)
|
||||
self.reciprocal_basis2pi = 2 * np.pi * self.reciprocal_basis1
|
||||
|
||||
def _process_planewave_angles(self): #feature: planewave
|
||||
import math
|
||||
pi2 = math.pi/2
|
||||
a = self.args
|
||||
a.chi = a.chi * pi2
|
||||
a.psi = a.psi * pi2
|
||||
a.theta = a.theta * pi2
|
||||
a.phi = a.phi * pi2
|
||||
|
||||
def _process_multi_particle(self): # feature: multi_particle
|
||||
a = self.args
|
||||
self.tmspecs = {}
|
||||
self.tmgens = {}
|
||||
self.bspecs = {}
|
||||
self.positions = {}
|
||||
pos13, pos23, pos33 = False, False, False # used to
|
||||
if len(a.position.keys()) == 0:
|
||||
warnings.warn("No particle position (-p or +p) specified, assuming single particle in the origin / single particle per unit cell!")
|
||||
a.position[None] = [(0.,0.,0.)]
|
||||
for poslabel in a.position.keys():
|
||||
try:
|
||||
lMax = a.lMax.get(poslabel, False) or a.lMax[None]
|
||||
radius = a.radius.get(poslabel, False) or a.radius[None]
|
||||
# Height is "inherited" only together with radius
|
||||
height = a.height.get(poslabel, None) if poslabel in a.radius.keys() else a.height.get(None, None)
|
||||
if hasattr(a, 'lMax_extend'):
|
||||
lMax_extend = a.lMax_extend.get(poslabel, False) or a.lMax_extend.get(None, False) or None
|
||||
else:
|
||||
lMax_extend = None
|
||||
material = a.material.get(poslabel, False) or a.material[None]
|
||||
except (TypeError, KeyError) as exc:
|
||||
if poslabel is None:
|
||||
raise ArgumentProcessingError("Unlabeled particles' positions (-p) specified, but some default particle properties are missing (--lMax, --radius, and --material have to be specified)") from exc
|
||||
else:
|
||||
raise ArgumentProcessingError(("Incomplete specification of '%s'-labeled particles: you must"
|
||||
"provide at least ++lMax, ++radius, ++material arguments with the label, or the fallback arguments"
|
||||
"--lMax, --radius, --material.")%(str(poslabel),)) from exc
|
||||
tmspec = (a.background, material, (radius, height, lMax_extend))
|
||||
self.tmspecs[poslabel] = tmspec
|
||||
self.tmgens[poslabel] = self._add_tmg(tmspec)
|
||||
self.bspecs[poslabel] = self._add_bspec(lMax)
|
||||
poslist_cured = []
|
||||
for pos in a.position[poslabel]:
|
||||
if len(pos) == 1:
|
||||
pos_cured = (0., 0., pos[0])
|
||||
pos13 = True
|
||||
elif len(pos) == 2:
|
||||
pos_cured = (pos[0], pos[1], 0.)
|
||||
pos23 = True
|
||||
elif len(pos) == 3:
|
||||
pos_cured = pos
|
||||
pos33 = True
|
||||
else:
|
||||
raise argparse.ArgumentTypeError("Each -p / +p argument requires 1 to 3 cartesian coordinates")
|
||||
poslist_cured.append(pos_cured)
|
||||
self.positions[poslabel] = poslist_cured
|
||||
if pos13 and pos23:
|
||||
warnings.warn("Both 1D and 2D position specifications used. The former are interpreted as z coordinates while the latter as x, y coordinates")
|
||||
|
||||
def get_particles(self):
|
||||
"""Creates a list of Particle instances that can be directly used in ScatteringSystem.create().
|
||||
|
||||
Assumes that self._process_multi_particle() has been already called.
|
||||
"""
|
||||
from .qpms_c import Particle
|
||||
plist = []
|
||||
for poslabel, poss in self.positions.items():
|
||||
t = self.tmgens[poslabel]
|
||||
bspec = self.bspecs[poslabel]
|
||||
plist.extend([Particle(pos, t, bspec=bspec) for pos in poss])
|
||||
return plist
|
||||
|
||||
#TODO perhaps move into another module
|
||||
def annotate_pdf_metadata(pdfPages, scriptname=None, keywords=None, author=None, title=None, subject=None, **kwargs):
|
||||
"""Adds QPMS version-related metadata to a matplotlib PdfPages object
|
||||
|
||||
Use before closing the PDF file.
|
||||
"""
|
||||
from .qpms_c import qpms_library_version
|
||||
d = pdfPages.infodict()
|
||||
d['Creator'] = "QPMS%s (lib rev. %s), https://qpms.necada.org" % (
|
||||
"" if scriptname is None else (" "+scriptname), qpms_library_version())
|
||||
if author is not None:
|
||||
d['Author'] = author
|
||||
if title is not None:
|
||||
d['Title'] = title
|
||||
if subject is not None:
|
||||
d['Subject'] = subject
|
||||
if keywords is not None:
|
||||
d['Keywords'] = ' '.join(keywords)
|
||||
d.update(kwargs)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <gsl/gsl_sf_bessel.h>
|
||||
#include <complex.h>
|
||||
#include "qpms_error.h"
|
||||
#include <amos.h>
|
||||
#include <camos.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef M_LN2
|
||||
|
@ -52,6 +52,11 @@ static inline complex double spherical_yn(qpms_l_t l, complex double z) {
|
|||
qpms_errno_t qpms_sph_bessel_realx_fill(qpms_bessel_t typ, qpms_l_t lmax, double x, complex double *result_array) {
|
||||
int retval;
|
||||
double tmparr[lmax+1];
|
||||
if (typ != QPMS_BESSEL_REGULAR && x == 0) {
|
||||
for (int l = 0; l <= lmax; ++l) result_array[l] = NAN + I*NAN;
|
||||
QPMS_WARN("Evaluating singular Bessel functions at zero!");
|
||||
return QPMS_SUCCESS; // Really?
|
||||
}
|
||||
switch(typ) {
|
||||
case QPMS_BESSEL_REGULAR:
|
||||
retval = gsl_sf_bessel_jl_steed_array(lmax, x, tmparr);
|
||||
|
@ -84,7 +89,8 @@ qpms_errno_t qpms_sph_bessel_realx_fill(qpms_bessel_t typ, qpms_l_t lmax, double
|
|||
|
||||
// TODO DOC
|
||||
qpms_errno_t qpms_sph_bessel_fill(qpms_bessel_t typ, qpms_l_t lmax, complex double x, complex double *res) {
|
||||
if(!cimag(x))
|
||||
if(!cimag(x) &&
|
||||
creal(x) < 10000) // For large arguments (around 30000 or more), gsl_sf_bessel_jl_steed_array fails
|
||||
return qpms_sph_bessel_realx_fill(typ, lmax, creal(x), res);
|
||||
else if (isnan(creal(x)) || isnan(cimag(x)))
|
||||
for(qpms_l_t l = 0; l <= lmax; ++l) res[l] = NAN + I*NAN;
|
||||
|
@ -92,30 +98,32 @@ qpms_errno_t qpms_sph_bessel_fill(qpms_bessel_t typ, qpms_l_t lmax, complex doub
|
|||
else if (fpclassify(creal(x)) == FP_INFINITE)
|
||||
for(qpms_l_t l = 0; l <= lmax; ++l) res[l] = INFINITY + I * INFINITY;
|
||||
else {
|
||||
const DOUBLE_PRECISION_t zr = creal(x), zi = cimag(x), fnu = 0.5;
|
||||
const INTEGER_t n = lmax + 1, kode = 1 /* No exponential scaling */;
|
||||
DOUBLE_PRECISION_t cyr[n], cyi[n];
|
||||
INTEGER_t ierr, nz;
|
||||
try_again: ;
|
||||
int retry_counter = 0;
|
||||
const double zr = creal(x), zi = cimag(x), fnu = 0.5;
|
||||
const int n = lmax + 1, kode = 1 /* No exponential scaling */;
|
||||
double cyr[n], cyi[n];
|
||||
int ierr, nz;
|
||||
unsigned int kindchar; // Only for error output
|
||||
const complex double prefac = csqrt(M_PI_2/x);
|
||||
switch(typ) {
|
||||
case QPMS_BESSEL_REGULAR:
|
||||
kindchar = 'j';
|
||||
amos_zbesj(&zr, &zi, &fnu, &kode, &n, cyr, cyi, &nz, &ierr);
|
||||
ierr = camos_zbesj(zr, zi, fnu, kode, n, cyr, cyi, &nz);
|
||||
break;
|
||||
case QPMS_BESSEL_SINGULAR:
|
||||
kindchar = 'y';
|
||||
{
|
||||
DOUBLE_PRECISION_t cwrkr[lmax + 1], cwrki[lmax + 1];
|
||||
amos_zbesy(&zr, &zi, &fnu, &kode, &n, cyr, cyi, &nz, cwrkr, cwrki, &ierr);
|
||||
double cwrkr[lmax + 1], cwrki[lmax + 1];
|
||||
ierr = camos_zbesy(zr, zi, fnu, kode, n, cyr, cyi, &nz, cwrkr, cwrki);
|
||||
}
|
||||
break;
|
||||
case QPMS_HANKEL_PLUS:
|
||||
case QPMS_HANKEL_MINUS:
|
||||
kindchar = 'h';
|
||||
{
|
||||
const INTEGER_t m = (typ == QPMS_HANKEL_PLUS) ? 1 : 2;
|
||||
amos_zbesh(&zr, &zi, &fnu, &kode, &m, &n, cyr, cyi, &nz, &ierr);
|
||||
const int m = (typ == QPMS_HANKEL_PLUS) ? 1 : 2;
|
||||
ierr = camos_zbesh(zr, zi, fnu, kode, m, n, cyr, cyi, &nz);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -126,14 +134,28 @@ qpms_errno_t qpms_sph_bessel_fill(qpms_bessel_t typ, qpms_l_t lmax, complex doub
|
|||
for (qpms_l_t l = 0; l <= lmax; ++l)
|
||||
res[l] = prefac * (cyr[l] + I * cyi[l]);
|
||||
if (ierr == 3)
|
||||
QPMS_WARN("Amos's zbes%c computation done but losses of significance "
|
||||
"by argument reduction produce less than half of machine accuracy.",
|
||||
kindchar);
|
||||
if (creal(x) >= 10000) {
|
||||
QPMS_WARN_ONCE("Due to large argument, "
|
||||
"Amos's zbes%c computation done but losses of significance "
|
||||
"by argument reduction produce less than half of machine accuracy. "
|
||||
"This warning is shown only once.",
|
||||
kindchar);
|
||||
} else {
|
||||
QPMS_WARN("Amos's zbes%c computation done but losses of significance "
|
||||
"by argument reduction produce less than half of machine accuracy.",
|
||||
kindchar);
|
||||
}
|
||||
return QPMS_SUCCESS; //TODO maybe something else if ierr == 3
|
||||
}
|
||||
else
|
||||
QPMS_PR_ERROR("Amos's zbes%c failed with ierr == %d.",
|
||||
kindchar, (int) ierr);
|
||||
else {
|
||||
if (retry_counter < 5) {
|
||||
QPMS_WARN("Amos's zbes%c failed with ierr == %d (lMax = %d, x = %+.16g%+.16gi). Retrying.\n",
|
||||
kindchar, (int) ierr, lmax, creal(x), cimag(x));
|
||||
++retry_counter;
|
||||
goto try_again;
|
||||
} else QPMS_PR_ERROR("Amos's zbes%c failed with ierr == %d (lMax = %d, x = %+.16g%+.16gi).",
|
||||
kindchar, (int) ierr, lmax, creal(x), cimag(x));
|
||||
}
|
||||
}
|
||||
return QPMS_SUCCESS;
|
||||
}
|
||||
|
|
403
qpms/beyn.c
403
qpms/beyn.c
|
@ -1,8 +1,5 @@
|
|||
#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1]
|
||||
|
||||
#define cg2s(x) gsl_complex_tostd(x)
|
||||
#define cs2g(x) gsl_complex_fromstd(x)
|
||||
|
||||
#include <complex.h>
|
||||
#include <lapacke.h>
|
||||
#include <stdio.h>
|
||||
|
@ -10,30 +7,25 @@
|
|||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include "qpms_error.h"
|
||||
|
||||
// Maybe GSL works?
|
||||
#include <gsl/gsl_matrix.h>
|
||||
#include <gsl/gsl_complex_math.h>
|
||||
#include <gsl/gsl_linalg.h>
|
||||
#include <gsl/gsl_blas.h>
|
||||
#include <gsl/gsl_eigen.h>
|
||||
#include <string.h>
|
||||
#include <cblas.h>
|
||||
|
||||
#include "beyn.h"
|
||||
#define SQ(x) ((x)*(x))
|
||||
|
||||
STATIC_ASSERT((sizeof(lapack_complex_double) == sizeof(gsl_complex)), lapack_and_gsl_complex_must_be_consistent);
|
||||
|
||||
// matrix access
|
||||
#define MAT(mat_, n_rows_, n_cols_, i_row_, i_col_) (mat_[(n_cols_) * (i_row_) + (i_col_)])
|
||||
|
||||
typedef struct BeynSolver
|
||||
{
|
||||
int M; // dimension of matrices
|
||||
int L; // number of columns of VHat matrix
|
||||
|
||||
gsl_vector_complex *eigenvalues, *eigenvalue_errors;
|
||||
gsl_matrix_complex *eigenvectors;
|
||||
gsl_matrix_complex *A0, *A1, *A0_coarse, *A1_coarse, *MInvVHat;
|
||||
gsl_matrix_complex *VHat;
|
||||
gsl_vector *Sigma, *residuals;
|
||||
complex double *eigenvalues, *eigenvalue_errors; // [L]
|
||||
complex double *eigenvectors; // [L][M] (!!!)
|
||||
complex double *A0, *A1, *A0_coarse, *A1_coarse, *MInvVHat; // [M][L]
|
||||
complex double *VHat; // [M][L]
|
||||
double *Sigma, *residuals; // [L]
|
||||
} BeynSolver;
|
||||
|
||||
// constructor, destructor
|
||||
|
@ -253,39 +245,40 @@ beyn_contour_t *beyn_contour_kidney(complex double centre, double rRe,
|
|||
return c;
|
||||
}
|
||||
|
||||
void beyn_result_gsl_free(beyn_result_gsl_t *r) {
|
||||
void beyn_result_free(beyn_result_t *r) {
|
||||
if(r) {
|
||||
gsl_vector_complex_free(r->eigval);
|
||||
gsl_vector_complex_free(r->eigval_err);
|
||||
gsl_vector_free(r->residuals);
|
||||
gsl_matrix_complex_free(r->eigvec);
|
||||
gsl_vector_free(r->ranktest_SV);
|
||||
free(r->eigval);
|
||||
free(r->eigval_err);
|
||||
free(r->residuals);
|
||||
free(r->eigvec);
|
||||
free(r->ranktest_SV);
|
||||
free(r);
|
||||
}
|
||||
}
|
||||
|
||||
BeynSolver *BeynSolver_create(int M, int L)
|
||||
{
|
||||
BeynSolver *solver= (BeynSolver *)malloc(sizeof(*solver));
|
||||
BeynSolver *solver;
|
||||
QPMS_CRASHING_CALLOC(solver, 1, sizeof(*solver));
|
||||
|
||||
solver->M = M;
|
||||
solver->L = L;
|
||||
QPMS_ENSURE(L <= M, "We expect L <= M, but we got L = %d, M = %d ", L, M);
|
||||
|
||||
// storage for eigenvalues and eigenvectors
|
||||
solver->eigenvalues = gsl_vector_complex_calloc(L);
|
||||
solver->eigenvalue_errors = gsl_vector_complex_calloc(L);
|
||||
solver->residuals = gsl_vector_calloc(L);
|
||||
solver->eigenvectors = gsl_matrix_complex_calloc(M, L);
|
||||
QPMS_CRASHING_CALLOC(solver->eigenvalues, L, sizeof(complex double));
|
||||
QPMS_CRASHING_CALLOC(solver->eigenvalue_errors, L, sizeof(complex double));
|
||||
QPMS_CRASHING_CALLOC(solver->residuals, L, sizeof(double));
|
||||
QPMS_CRASHING_CALLOC(solver->eigenvectors, L * M, sizeof(complex double));
|
||||
|
||||
// storage for singular values, random VHat matrix, etc. used in algorithm
|
||||
solver->A0 = gsl_matrix_complex_calloc(M,L);
|
||||
solver->A1 = gsl_matrix_complex_calloc(M,L);
|
||||
solver->A0_coarse = gsl_matrix_complex_calloc(M,L);
|
||||
solver->A1_coarse = gsl_matrix_complex_calloc(M,L);
|
||||
solver->MInvVHat = gsl_matrix_complex_calloc(M,L);
|
||||
solver->VHat = gsl_matrix_complex_calloc(M,L);
|
||||
solver->Sigma = gsl_vector_calloc(L);
|
||||
QPMS_CRASHING_CALLOC(solver->A0, M * L, sizeof(complex double));
|
||||
QPMS_CRASHING_CALLOC(solver->A1, M * L, sizeof(complex double));
|
||||
QPMS_CRASHING_CALLOC(solver->A0_coarse, M * L, sizeof(complex double));
|
||||
QPMS_CRASHING_CALLOC(solver->A1_coarse, M * L, sizeof(complex double));
|
||||
QPMS_CRASHING_CALLOC(solver->MInvVHat, M * L, sizeof(complex double));
|
||||
QPMS_CRASHING_CALLOC(solver->VHat, M * L, sizeof(complex double));
|
||||
QPMS_CRASHING_CALLOC(solver->Sigma, L, sizeof(double));
|
||||
// Beyn Step 1: Generate random matrix VHat
|
||||
BeynSolver_srandom(solver,(unsigned)time(NULL));
|
||||
|
||||
|
@ -295,30 +288,30 @@ BeynSolver *BeynSolver_create(int M, int L)
|
|||
|
||||
void BeynSolver_free(BeynSolver *solver)
|
||||
{
|
||||
gsl_vector_complex_free(solver->eigenvalues);
|
||||
gsl_vector_complex_free(solver->eigenvalue_errors);
|
||||
gsl_matrix_complex_free(solver->eigenvectors);
|
||||
free(solver->eigenvalues);
|
||||
free(solver->eigenvalue_errors);
|
||||
free(solver->eigenvectors);
|
||||
|
||||
gsl_matrix_complex_free(solver->A0);
|
||||
gsl_matrix_complex_free(solver->A1);
|
||||
gsl_matrix_complex_free(solver->A0_coarse);
|
||||
gsl_matrix_complex_free(solver->A1_coarse);
|
||||
gsl_matrix_complex_free(solver->MInvVHat);
|
||||
gsl_vector_free(solver->Sigma);
|
||||
gsl_vector_free(solver->residuals);
|
||||
gsl_matrix_complex_free(solver->VHat);
|
||||
free(solver->A0);
|
||||
free(solver->A1);
|
||||
free(solver->A0_coarse);
|
||||
free(solver->A1_coarse);
|
||||
free(solver->MInvVHat);
|
||||
free(solver->Sigma);
|
||||
free(solver->residuals);
|
||||
free(solver->VHat);
|
||||
|
||||
free(solver);
|
||||
}
|
||||
|
||||
void BeynSolver_free_partial(BeynSolver *solver)
|
||||
{
|
||||
gsl_matrix_complex_free(solver->A0);
|
||||
gsl_matrix_complex_free(solver->A1);
|
||||
gsl_matrix_complex_free(solver->A0_coarse);
|
||||
gsl_matrix_complex_free(solver->A1_coarse);
|
||||
gsl_matrix_complex_free(solver->MInvVHat);
|
||||
gsl_matrix_complex_free(solver->VHat);
|
||||
free(solver->A0);
|
||||
free(solver->A1);
|
||||
free(solver->A0_coarse);
|
||||
free(solver->A1_coarse);
|
||||
free(solver->MInvVHat);
|
||||
free(solver->VHat);
|
||||
|
||||
free(solver);
|
||||
}
|
||||
|
@ -328,11 +321,8 @@ void BeynSolver_srandom(BeynSolver *solver, unsigned int RandSeed)
|
|||
if (RandSeed==0)
|
||||
RandSeed=time(0);
|
||||
srandom(RandSeed);
|
||||
gsl_matrix_complex *VHat=solver->VHat;
|
||||
for(int nr=0; nr<VHat->size1; nr++)
|
||||
for(int nc=0; nc<VHat->size2; nc++)
|
||||
gsl_matrix_complex_set(VHat,nr,nc,cs2g(zrandN(1, 0)));
|
||||
|
||||
for(size_t i = 0; i < solver->M * solver->L; ++i)
|
||||
solver->VHat[i] = zrandN(1, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -342,44 +332,42 @@ void BeynSolver_srandom(BeynSolver *solver, unsigned int RandSeed)
|
|||
* and eigenvectors
|
||||
*/
|
||||
|
||||
static int beyn_process_matrices(BeynSolver *solver, beyn_function_M_gsl_t M_function,
|
||||
static int beyn_process_matrices(BeynSolver *solver, beyn_function_M_t M_function,
|
||||
void *Params,
|
||||
gsl_matrix_complex *A0, gsl_matrix_complex *A1, double complex z0,
|
||||
gsl_vector_complex *eigenvalues, gsl_matrix_complex *eigenvectors, const double rank_tol, size_t rank_sel_min, const double res_tol)
|
||||
complex double *A0, complex double *A1, double complex z0,
|
||||
complex double *eigenvalues, complex double *eigenvectors, const double rank_tol, size_t rank_sel_min, const double res_tol)
|
||||
{
|
||||
const size_t m = solver->M;
|
||||
const size_t l = solver->L;
|
||||
gsl_vector *Sigma = solver->Sigma;
|
||||
double *Sigma = solver->Sigma;
|
||||
|
||||
int verbose = 1; // TODO
|
||||
|
||||
// Beyn Step 3: Compute SVD: A0 = V0_full * Sigma * W0T_full
|
||||
if(verbose) printf(" Beyn: computing SVD...\n");
|
||||
gsl_matrix_complex* V0_full = gsl_matrix_complex_alloc(m,l);
|
||||
gsl_matrix_complex_memcpy(V0_full,A0);
|
||||
gsl_matrix_complex* W0T_full = gsl_matrix_complex_alloc(l,l);
|
||||
QPMS_ENSURE(Sigma->stride == 1, "Sigma vector stride must be 1 for LAPACKE_zgesdd, got %zd.", Sigma->stride);
|
||||
QPMS_ENSURE(V0_full->size1 >= V0_full->size2, "m = %zd, l = %zd, what the hell?");
|
||||
complex double *V0_full;
|
||||
QPMS_CRASHING_MALLOCPY(V0_full, A0, m * l * sizeof(complex double));
|
||||
complex double *W0T_full; QPMS_CRASHING_MALLOC(W0T_full, l * l * sizeof(complex double));
|
||||
QPMS_ENSURE_SUCCESS(LAPACKE_zgesdd(LAPACK_ROW_MAJOR, // A = U*Σ*conjg(V')
|
||||
'O' /*jobz, 'O' overwrites a with U and saves conjg(V') in vt if m >= n, i.e. if M >= L, which holds*/,
|
||||
V0_full->size1 /* m, number of rows */,
|
||||
V0_full->size2 /* n, number of columns */,
|
||||
(lapack_complex_double *)(V0_full->data) /*a*/,
|
||||
V0_full->tda /*lda*/,
|
||||
Sigma->data /*s*/,
|
||||
m, // V0_full->size1 /* m, number of rows */,
|
||||
l, // V0_full->size2 /* n, number of columns */,
|
||||
V0_full, //(lapack_complex_double *)(V0_full->data) /*a*/,
|
||||
l, //V0_full->tda /*lda*/,
|
||||
Sigma, //Sigma->data /*s*/,
|
||||
NULL /*u; not used*/,
|
||||
m /*ldu; should not be really used but lapacke requires it for some obscure reason*/,
|
||||
(lapack_complex_double *)W0T_full->data /*vt*/,
|
||||
W0T_full->tda /*ldvt*/
|
||||
W0T_full, //(lapack_complex_double *)W0T_full->data /*vt*/,
|
||||
l //W0T_full->tda /*ldvt*/
|
||||
));
|
||||
|
||||
|
||||
// Beyn Step 4: Rank test for Sigma
|
||||
// compute effective rank K (number of eigenvalue candidates)
|
||||
int K=0;
|
||||
for (int k=0; k<Sigma->size /* this is l, actually */; k++) {
|
||||
if (verbose) printf("Beyn: SV(%d)=%e\n",k,gsl_vector_get(Sigma, k));
|
||||
if (k < rank_sel_min || gsl_vector_get(Sigma, k) > rank_tol)
|
||||
for (int k=0; k < l/* k<Sigma->size*/ /* this is l, actually */; k++) {
|
||||
if (verbose) printf("Beyn: SV(%d)=%e\n",k, Sigma[k] );
|
||||
if (k < rank_sel_min || Sigma[k] > rank_tol)
|
||||
K++;
|
||||
}
|
||||
if (verbose)printf(" Beyn: %d/%zd relevant singular values\n",K,l);
|
||||
|
@ -390,49 +378,48 @@ static int beyn_process_matrices(BeynSolver *solver, beyn_function_M_gsl_t M_fun
|
|||
|
||||
// Beyn step 5: B = V0' * A1 * W0 * Sigma^-1
|
||||
// set V0, W0T = matrices of first K right, left singular vectors
|
||||
gsl_matrix_complex *V0 = gsl_matrix_complex_alloc(m,K);
|
||||
gsl_matrix_complex *W0T= gsl_matrix_complex_alloc(K,l);
|
||||
complex double *V0, *W0T;
|
||||
QPMS_CRASHING_MALLOC(V0, m * K * sizeof(complex double));
|
||||
QPMS_CRASHING_MALLOC(W0T, K * l * sizeof(complex double));
|
||||
|
||||
// TODO this is stupid, some parts could be handled simply by realloc.
|
||||
for (int k = 0; k < K; ++k) {
|
||||
gsl_vector_complex_view tmp;
|
||||
tmp = gsl_matrix_complex_column(V0_full, k);
|
||||
gsl_matrix_complex_set_col(V0, k, &(tmp.vector));
|
||||
tmp = gsl_matrix_complex_row(W0T_full, k);
|
||||
gsl_matrix_complex_set_row(W0T, k, &(tmp.vector));
|
||||
for(int i = 0; i < m; ++i)
|
||||
MAT(V0, m, K, i, k) = MAT(V0_full, m, l, i, k);
|
||||
for(int j = 0; j < l; ++j)
|
||||
MAT(W0T, K, l, k, j) = MAT(W0T_full, l, l, k, j);
|
||||
}
|
||||
free(V0_full);
|
||||
free(W0T_full);
|
||||
|
||||
gsl_matrix_complex_free(V0_full);
|
||||
gsl_matrix_complex_free(W0T_full);
|
||||
|
||||
gsl_matrix_complex *TM2 = gsl_matrix_complex_calloc(K,l);
|
||||
gsl_matrix_complex *B = gsl_matrix_complex_calloc(K,K);
|
||||
complex double *TM2, *B;
|
||||
QPMS_CRASHING_CALLOC(TM2, K * l, sizeof(complex double));
|
||||
QPMS_CRASHING_CALLOC(B, K * K, sizeof(complex double));
|
||||
|
||||
if(verbose) printf(" Multiplying V0*A1->TM...\n");
|
||||
|
||||
const gsl_complex one = gsl_complex_rect(1,0);
|
||||
const gsl_complex zero = gsl_complex_rect(0,0);
|
||||
gsl_blas_zgemm(CblasConjTrans, CblasNoTrans, one,
|
||||
V0, A1, zero, TM2);
|
||||
// dims: V0[m,K], A1[m,l], TM2[K,l]
|
||||
const complex double one = 1, zero = 0;
|
||||
cblas_zgemm(CblasRowMajor, CblasConjTrans, CblasNoTrans, K, l, m,
|
||||
&one, V0, K, A1, l, &zero, TM2, l);
|
||||
|
||||
|
||||
if(verbose) printf(" Multiplying TM*W0T->B...\n");
|
||||
|
||||
gsl_blas_zgemm(CblasNoTrans, CblasConjTrans, one,
|
||||
TM2, W0T, zero, B);
|
||||
// TM2, W0T, zero, B);
|
||||
// DIMS: TM2[K,l], W0T[K,l], B[K,K]
|
||||
cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasConjTrans, K, K, l,
|
||||
&one, TM2, l, W0T, l, &zero, B, K);
|
||||
|
||||
gsl_matrix_complex_free(W0T);
|
||||
gsl_matrix_complex_free(TM2);
|
||||
free(W0T);
|
||||
free(TM2);
|
||||
|
||||
if(verbose) printf(" Scaling B <- B*Sigma^{-1}\n");
|
||||
gsl_vector_complex *tmp = gsl_vector_complex_calloc(K);
|
||||
for(int i = 0; i < K; i++) {
|
||||
gsl_matrix_complex_get_col(tmp, B, i);
|
||||
gsl_vector_complex_scale(tmp, gsl_complex_rect(1.0/gsl_vector_get(Sigma,i), 0));
|
||||
gsl_matrix_complex_set_col(B,i,tmp);
|
||||
for(int j = 0; j < K; j++)
|
||||
MAT(B, K, K, j, i) /= Sigma[i];
|
||||
}
|
||||
gsl_vector_complex_free(tmp);
|
||||
|
||||
//for(int m=0; m<K; m++) // B <- B * Sigma^{-1}
|
||||
|
||||
// Beyn step 6.
|
||||
// Eigenvalue decomposition B -> S*Lambda*S'
|
||||
/* According to Beyn's paper (Algorithm 1), one should check conditioning
|
||||
|
@ -444,95 +431,102 @@ static int beyn_process_matrices(BeynSolver *solver, beyn_function_M_gsl_t M_fun
|
|||
*/
|
||||
if(verbose) printf(" Eigensolving (%i,%i)\n",K,K);
|
||||
|
||||
gsl_vector_complex *Lambda = gsl_vector_complex_alloc(K); // eigenvalues
|
||||
gsl_matrix_complex *S = gsl_matrix_complex_alloc(K,K); // eigenvectors
|
||||
complex double *Lambda /* eigenvalues */ , *S /* eigenvector */;
|
||||
QPMS_CRASHING_MALLOC(Lambda, K * sizeof(complex double));
|
||||
QPMS_CRASHING_MALLOC(S, K * K * sizeof(complex double));
|
||||
|
||||
QPMS_ENSURE(Sigma->stride == 1, "Sigma vector stride must be 1 for LAPACKE_zgesdd, got %zd.", Sigma->stride);
|
||||
QPMS_ENSURE(Lambda->stride == 1, "Lambda vector stride must be 1 for LAPACKE_zgesdd, got %zd.", Sigma->stride);
|
||||
// dims: B[K,K], S[K,K], Lambda[K]
|
||||
QPMS_ENSURE_SUCCESS(LAPACKE_zgeev(
|
||||
LAPACK_ROW_MAJOR,
|
||||
'N' /* jobvl; don't compute left eigenvectors */,
|
||||
'V' /* jobvr; do compute right eigenvectors */,
|
||||
K /* n */,
|
||||
(lapack_complex_double *)(B->data) /* a */,
|
||||
B->tda /* lda */,
|
||||
(lapack_complex_double *) Lambda->data /* w */,
|
||||
B, //(lapack_complex_double *)(B->data) /* a */,
|
||||
K, //B->tda /* lda */,
|
||||
Lambda, //(lapack_complex_double *) Lambda->data /* w */,
|
||||
NULL /* vl */,
|
||||
m /* ldvl, not used by for some reason needed */,
|
||||
(lapack_complex_double *)(S->data)/* vr */,
|
||||
S->tda/* ldvr */
|
||||
m /* ldvl, not used but for some reason needed */,
|
||||
S, //(lapack_complex_double *)(S->data)/* vr */,
|
||||
K //S->tda/* ldvr */
|
||||
));
|
||||
|
||||
gsl_matrix_complex_free(B);
|
||||
free(B);
|
||||
|
||||
// V0S <- V0*S
|
||||
printf("Multiplying V0*S...\n");
|
||||
gsl_matrix_complex *V0S = gsl_matrix_complex_alloc(m, K);
|
||||
QPMS_ENSURE_SUCCESS(gsl_blas_zgemm(CblasNoTrans, CblasNoTrans,
|
||||
one, V0, S, zero, V0S));
|
||||
complex double *V0S;
|
||||
QPMS_CRASHING_MALLOC(V0S, m * K * sizeof(complex double));
|
||||
// dims: V0[m,K], S[K,K], V0S[m,K]
|
||||
cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, K, K,
|
||||
&one, V0, K, S, K, &zero, V0S, K);
|
||||
|
||||
gsl_matrix_complex_free(V0);
|
||||
free(V0);
|
||||
|
||||
// FIXME!!! make clear relation between KRetained and K in the results!
|
||||
// (If they differ, there are possibly some spurious eigenvalues.)
|
||||
int KRetained = 0;
|
||||
gsl_matrix_complex *Mmat = gsl_matrix_complex_alloc(m, m);
|
||||
gsl_vector_complex *MVk = gsl_vector_complex_alloc(m);
|
||||
complex double *Mmat, *MVk;
|
||||
QPMS_CRASHING_MALLOC(Mmat, m * m * sizeof(complex double));
|
||||
QPMS_CRASHING_MALLOC(MVk, m * sizeof(complex double));
|
||||
for (int k = 0; k < K; ++k) {
|
||||
const gsl_complex zgsl = gsl_complex_add(gsl_complex_rect(creal(z0), cimag(z0)), gsl_vector_complex_get(Lambda, k));
|
||||
const complex double z = GSL_REAL(zgsl) + I*GSL_IMAG(zgsl);
|
||||
gsl_vector_complex_const_view Vk = gsl_matrix_complex_const_column(V0S, k);
|
||||
const complex double z = z0 + Lambda[k];
|
||||
|
||||
double residual = 0;
|
||||
if(res_tol > 0) {
|
||||
QPMS_ENSURE_SUCCESS(M_function(Mmat, z, Params));
|
||||
QPMS_ENSURE_SUCCESS(gsl_blas_zgemv(CblasNoTrans, one, Mmat, &(Vk.vector), zero, MVk));
|
||||
residual = gsl_blas_dznrm2(MVk);
|
||||
QPMS_ENSURE_SUCCESS(M_function(Mmat, m, z, Params));
|
||||
// Vk[i] == V0S[i, k]; dims: Mmat[m,m], Vk[m] (V0S[m, K]), MVk[m]
|
||||
cblas_zgemv(CblasRowMajor, CblasNoTrans, m, m,
|
||||
&one, Mmat, m, &MAT(V0S, m, K, 0, k), K /* stride of Vk in V0S */,
|
||||
&zero, MVk, 1);
|
||||
|
||||
residual = cblas_dznrm2(m, MVk, 1);
|
||||
if (verbose) printf("Beyn: Residual(%i)=%e\n",k,residual);
|
||||
}
|
||||
if (res_tol > 0 && residual > res_tol) continue;
|
||||
|
||||
gsl_vector_complex_set(eigenvalues, KRetained, zgsl);
|
||||
if(eigenvectors) {
|
||||
gsl_matrix_complex_set_row(eigenvectors, KRetained, &(Vk.vector));
|
||||
gsl_vector_set(solver->residuals, KRetained, residual);
|
||||
eigenvalues[KRetained] = z;
|
||||
if(eigenvectors) { // eigenvectors is NULL when calculating the "coarse" contour for error estimates
|
||||
for(int j = 0; j < m; ++j)
|
||||
MAT(eigenvectors, l, m, KRetained, j) = MAT(V0S, m, K, j, k);
|
||||
solver->residuals[KRetained] = residual;
|
||||
}
|
||||
++KRetained;
|
||||
}
|
||||
|
||||
gsl_matrix_complex_free(V0S);
|
||||
gsl_matrix_complex_free(Mmat);
|
||||
gsl_vector_complex_free(MVk);
|
||||
gsl_matrix_complex_free(S);
|
||||
gsl_vector_complex_free(Lambda);
|
||||
free(V0S);
|
||||
free(Mmat);
|
||||
free(MVk);
|
||||
free(S);
|
||||
free(Lambda);
|
||||
|
||||
return KRetained;
|
||||
}
|
||||
|
||||
|
||||
beyn_result_gsl_t *beyn_solve_gsl(const size_t m, const size_t l,
|
||||
beyn_function_M_gsl_t M_function, beyn_function_M_inv_Vhat_gsl_t M_inv_Vhat_function,
|
||||
beyn_result_t *beyn_solve(const size_t m, const size_t l,
|
||||
beyn_function_M_t M_function, beyn_function_M_inv_Vhat_t M_inv_Vhat_function,
|
||||
void *params, const beyn_contour_t *contour,
|
||||
double rank_tol, size_t rank_sel_min, double res_tol)
|
||||
{
|
||||
BeynSolver *solver = BeynSolver_create(m, l);
|
||||
|
||||
gsl_matrix_complex *A0 = solver->A0;
|
||||
gsl_matrix_complex *A1 = solver->A1;
|
||||
gsl_matrix_complex *A0_coarse = solver->A0_coarse;
|
||||
gsl_matrix_complex *A1_coarse = solver->A1_coarse;
|
||||
gsl_matrix_complex *MInvVHat = solver->MInvVHat;
|
||||
gsl_matrix_complex *VHat = solver->VHat;
|
||||
complex double *A0 = solver->A0;
|
||||
complex double *A1 = solver->A1;
|
||||
complex double *A0_coarse = solver->A0_coarse;
|
||||
complex double *A1_coarse = solver->A1_coarse;
|
||||
complex double *MInvVHat = solver->MInvVHat;
|
||||
complex double *VHat = solver->VHat;
|
||||
|
||||
/***************************************************************/
|
||||
/* evaluate contour integrals by numerical quadrature to get */
|
||||
/* A0 and A1 matrices */
|
||||
/***************************************************************/
|
||||
|
||||
gsl_matrix_complex_set_zero(A0);
|
||||
gsl_matrix_complex_set_zero(A1);
|
||||
gsl_matrix_complex_set_zero(A0_coarse);
|
||||
gsl_matrix_complex_set_zero(A1_coarse);
|
||||
// TODO zeroing probably redundant (Used calloc...)
|
||||
memset(A0, 0, m * l * sizeof(complex double));
|
||||
memset(A1, 0, m * l * sizeof(complex double));
|
||||
memset(A0_coarse, 0, m * l * sizeof(complex double));
|
||||
memset(A1_coarse, 0, m * l * sizeof(complex double));
|
||||
const size_t N = contour->n;
|
||||
if(N & 1) QPMS_WARN("Contour discretisation point number is odd (%zd),"
|
||||
" the error estimates might be a bit off.", N);
|
||||
|
@ -544,44 +538,57 @@ beyn_result_gsl_t *beyn_solve_gsl(const size_t m, const size_t l,
|
|||
const complex double z = contour->z_dz[n][0];
|
||||
const complex double dz = contour->z_dz[n][1];
|
||||
|
||||
gsl_matrix_complex_memcpy(MInvVHat, VHat);
|
||||
memcpy(MInvVHat, VHat, m * l * sizeof(complex double));
|
||||
|
||||
if(M_inv_Vhat_function) {
|
||||
QPMS_ENSURE_SUCCESS(M_inv_Vhat_function(MInvVHat, VHat, z, params));
|
||||
QPMS_ENSURE_SUCCESS(M_inv_Vhat_function(MInvVHat, m, l, VHat, z, params));
|
||||
} else {
|
||||
lapack_int *pivot;
|
||||
gsl_matrix_complex *Mmat = gsl_matrix_complex_alloc(m,m);
|
||||
QPMS_ENSURE_SUCCESS(M_function(Mmat, z, params));
|
||||
complex double *Mmat;
|
||||
QPMS_CRASHING_MALLOC(Mmat, m * m * sizeof(complex double));
|
||||
QPMS_ENSURE_SUCCESS(M_function(Mmat, m, z, params));
|
||||
QPMS_CRASHING_MALLOC(pivot, sizeof(lapack_int) * m);
|
||||
#if 0
|
||||
QPMS_ENSURE_SUCCESS(LAPACKE_zgetrf(LAPACK_ROW_MAJOR,
|
||||
m /*m*/, m /*n*/,(lapack_complex_double *) Mmat->data /*a*/, Mmat->tda /*lda*/, pivot /*ipiv*/));
|
||||
QPMS_ENSURE(MInvVHat->tda == l, "wut?");
|
||||
QPMS_ENSURE_SUCCESS(LAPACKE_zgetrs(LAPACK_ROW_MAJOR, 'N' /*trans*/,
|
||||
m /*n*/, l/*nrhs*/, (lapack_complex_double *)(Mmat->data) /*a*/, Mmat->tda /*lda*/, pivot/*ipiv*/,
|
||||
(lapack_complex_double *)(MInvVHat->data) /*b*/, MInvVHat->tda/*ldb*/));
|
||||
#endif
|
||||
QPMS_ENSURE_SUCCESS(LAPACKE_zgetrf(LAPACK_ROW_MAJOR,
|
||||
m /*m*/, m /*n*/, Mmat /*a*/, m /*lda*/, pivot /*ipiv*/));
|
||||
QPMS_ENSURE_SUCCESS(LAPACKE_zgetrs(LAPACK_ROW_MAJOR, 'N' /*trans*/,
|
||||
m /*n*/, l/*nrhs*/, Mmat /*a*/, m /*lda*/, pivot/*ipiv*/,
|
||||
MInvVHat /*b*/, l /*ldb*/));
|
||||
|
||||
free(pivot);
|
||||
gsl_matrix_complex_free(Mmat);
|
||||
free(Mmat);
|
||||
}
|
||||
|
||||
gsl_matrix_complex_scale(MInvVHat, cs2g(dz));
|
||||
gsl_matrix_complex_add(A0, MInvVHat);
|
||||
for(size_t i = 0; i < m * l; ++i)
|
||||
MInvVHat[i] *= dz;
|
||||
for(size_t i = 0; i < m * l; ++i)
|
||||
A0[i] += MInvVHat[i];
|
||||
if((n%2)==0) {
|
||||
gsl_matrix_complex_add(A0_coarse, MInvVHat);
|
||||
gsl_matrix_complex_add(A0_coarse, MInvVHat);
|
||||
for(size_t i = 0; i < m * l; ++i)
|
||||
A0_coarse[i] += 2 * MInvVHat[i];
|
||||
}
|
||||
|
||||
gsl_matrix_complex_scale(MInvVHat, cs2g(z - z0)); // A_1 scaling as in Beyn's Remark 3.2(b) for numerical stability.
|
||||
gsl_matrix_complex_add(A1, MInvVHat);
|
||||
// A_1 scaling as in Beyn's Remark 3.2(b) for numerical stability.
|
||||
for(size_t i = 0; i < m * l; ++i)
|
||||
MInvVHat[i] *= (z - z0);
|
||||
for(size_t i = 0; i < m * l; ++i)
|
||||
A1[i] += MInvVHat[i];
|
||||
if((n%2)==0) {
|
||||
gsl_matrix_complex_add(A1_coarse, MInvVHat);
|
||||
gsl_matrix_complex_add(A1_coarse, MInvVHat);
|
||||
for(size_t i = 0; i < m * l; ++i)
|
||||
A1_coarse[i] += 2 * MInvVHat[i];
|
||||
}
|
||||
}
|
||||
|
||||
gsl_vector_complex *eigenvalues = solver->eigenvalues;
|
||||
gsl_vector_complex *eigenvalue_errors = solver->eigenvalue_errors;
|
||||
gsl_matrix_complex *eigenvectors = solver->eigenvectors;
|
||||
complex double *eigenvalues = solver->eigenvalues;
|
||||
complex double *eigenvalue_errors = solver->eigenvalue_errors;
|
||||
complex double *eigenvectors = solver->eigenvectors;
|
||||
|
||||
// Repeat Steps 3–6 with rougher contour approximation to get an error estimate.
|
||||
int K_coarse = beyn_process_matrices(solver, M_function, params, A0_coarse, A1_coarse, z0, eigenvalue_errors, /*eigenvectors_coarse*/ NULL, rank_tol, rank_sel_min, res_tol);
|
||||
|
@ -589,79 +596,23 @@ beyn_result_gsl_t *beyn_solve_gsl(const size_t m, const size_t l,
|
|||
|
||||
// Beyn Steps 3–6
|
||||
int K = beyn_process_matrices(solver, M_function, params, A0, A1, z0, eigenvalues, eigenvectors, rank_tol, rank_sel_min, res_tol);
|
||||
gsl_blas_zaxpy(gsl_complex_rect(-1,0), eigenvalues, eigenvalue_errors);
|
||||
|
||||
beyn_result_gsl_t *result;
|
||||
QPMS_CRASHING_MALLOC(result, sizeof(beyn_result_gsl_t));
|
||||
const complex double minusone = -1.;
|
||||
//TODO maybe change the sizes to correspend to retained eigval count K, not l
|
||||
cblas_zaxpy(l, &minusone, eigenvalues, 1, eigenvalue_errors, 1);
|
||||
|
||||
beyn_result_t *result;
|
||||
QPMS_CRASHING_MALLOC(result, sizeof(*result));
|
||||
result->eigval = solver->eigenvalues;
|
||||
result->eigval_err = solver->eigenvalue_errors;
|
||||
result->residuals = solver->residuals;
|
||||
result->eigvec = solver->eigenvectors;
|
||||
result->ranktest_SV = solver->Sigma;
|
||||
result->neig = K;
|
||||
result->vlen = m;
|
||||
|
||||
BeynSolver_free_partial(solver);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Wrapper of pure C array M-matrix function to GSL.
|
||||
|
||||
struct beyn_function_M_carr2gsl_param {
|
||||
beyn_function_M_t M_function;
|
||||
beyn_function_M_inv_Vhat_t M_inv_Vhat_function;
|
||||
void *param;
|
||||
};
|
||||
|
||||
static int beyn_function_M_carr2gsl(gsl_matrix_complex *target_M, complex double z, void *params)
|
||||
{
|
||||
struct beyn_function_M_carr2gsl_param *p = params;
|
||||
// These could rather be asserts.
|
||||
QPMS_ENSURE(target_M->size2 == target_M->tda, "Target GSL matrix is not a C-contiguous array. This is a bug, please report!");
|
||||
QPMS_ENSURE(target_M->size1 == target_M->size2, "Target is not a square matrix. This is a bug, please report!");
|
||||
return p->M_function((complex double *) target_M->data, target_M->size1, z, p->param);
|
||||
}
|
||||
|
||||
static int beyn_function_M_inv_Vhat_carr2gsl(gsl_matrix_complex *target,
|
||||
const gsl_matrix_complex *Vhat, complex double z, void *params)
|
||||
{
|
||||
QPMS_UNTESTED;
|
||||
struct beyn_function_M_carr2gsl_param *p = params;
|
||||
// These could rather be asserts.
|
||||
QPMS_ENSURE(target->size2 == target->tda, "Target GSL matrix is not a C-contiguous array. This is a bug, please report!");
|
||||
QPMS_ENSURE(Vhat->size2 == Vhat->tda, "Source GSL matrix is not a C-contiguous array. This is a bug, please report!");
|
||||
// TODO here I could also check whether Vhat and target have compatible sizes.
|
||||
return p->M_inv_Vhat_function((complex double *) target->data, target->size1, target->size2,
|
||||
(complex double *) Vhat->data, z, p->param);
|
||||
}
|
||||
|
||||
beyn_result_t *beyn_solve(size_t m, size_t l, beyn_function_M_t M, beyn_function_M_inv_Vhat_t M_inv_Vhat,
|
||||
void *params, const beyn_contour_t *contour, double rank_tol, size_t rank_sel_min, double res_tol) {
|
||||
struct beyn_function_M_carr2gsl_param p = {M, M_inv_Vhat, params};
|
||||
return beyn_result_from_beyn_result_gsl(
|
||||
beyn_solve_gsl(m, l, beyn_function_M_carr2gsl,
|
||||
(p.M_inv_Vhat_function) ? beyn_function_M_inv_Vhat_carr2gsl : NULL,
|
||||
(void *) &p, contour, rank_tol, rank_sel_min, res_tol)
|
||||
);
|
||||
}
|
||||
|
||||
beyn_result_t *beyn_result_from_beyn_result_gsl(beyn_result_gsl_t *g) {
|
||||
struct beyn_result_t *result;
|
||||
QPMS_CRASHING_MALLOC(result, sizeof(beyn_result_t));
|
||||
result->gsl = g;
|
||||
result->neig = result->gsl->neig;
|
||||
result->vlen = result->gsl->eigvec->size2;
|
||||
result->eigval = (complex double *) result->gsl->eigval->data;
|
||||
result->eigval_err = (complex double *) result->gsl->eigval_err->data;
|
||||
result->residuals = result->gsl->residuals->data;
|
||||
result->eigvec = (complex double *) result->gsl->eigvec->data;
|
||||
result->ranktest_SV = result->gsl->ranktest_SV->data;
|
||||
return result;
|
||||
}
|
||||
|
||||
void beyn_result_free(beyn_result_t *result) {
|
||||
if(result)
|
||||
beyn_result_gsl_free(result->gsl);
|
||||
free(result);
|
||||
}
|
||||
|
||||
|
|
51
qpms/beyn.h
51
qpms/beyn.h
|
@ -4,20 +4,10 @@
|
|||
#ifndef BEYN_H
|
||||
#define BEYN_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <complex.h>
|
||||
#include <gsl/gsl_matrix.h>
|
||||
#include <gsl/gsl_complex_math.h>
|
||||
|
||||
/// User-supplied function that provides the operator M(z) whose "roots" are to be found.
|
||||
/** GSL matrix version */
|
||||
typedef int (*beyn_function_M_gsl_t)(gsl_matrix_complex *target_M, complex double z, void *params);
|
||||
|
||||
/// (optional) User-supplied function that, given \f$ \hat V \f$, calculates \f$ M(z)^{-1} \hat V \f$.
|
||||
/** GSL matrix version */
|
||||
typedef int (*beyn_function_M_inv_Vhat_gsl_t)(gsl_matrix_complex *target_M_inv_Vhat,
|
||||
const gsl_matrix_complex *Vhat, complex double z, void *params);
|
||||
|
||||
/// User-supplied function that provides the operator M(z) whose "roots" are to be found.
|
||||
/// User-supplied function that provides the (row-major) m × m matrix M(z) whose "roots" are to be found.
|
||||
/** Pure C array version */
|
||||
typedef int (*beyn_function_M_t)(complex double *target_M, size_t m, complex double z, void *params);
|
||||
|
||||
|
@ -66,18 +56,6 @@ beyn_contour_t *beyn_contour_kidney(complex double centre, double halfax_re, dou
|
|||
size_t n, beyn_contour_halfellipse_orientation or);
|
||||
|
||||
|
||||
/// Beyn algorithm result structure (GSL matrix/vector version).
|
||||
typedef struct beyn_result_gsl_t {
|
||||
size_t neig; ///< Number of eigenvalues found (a bit redundant?).
|
||||
gsl_vector_complex *eigval;
|
||||
gsl_vector_complex *eigval_err;
|
||||
gsl_vector *residuals;
|
||||
gsl_matrix_complex *eigvec; // Rows are the eigenvectors
|
||||
gsl_vector *ranktest_SV;
|
||||
} beyn_result_gsl_t;
|
||||
|
||||
void beyn_result_gsl_free(beyn_result_gsl_t *result);
|
||||
|
||||
/// Beyn algorithm result structure (pure C array version).
|
||||
typedef struct beyn_result_t {
|
||||
size_t neig; ///< Number of eigenvalues found.
|
||||
|
@ -88,31 +66,11 @@ typedef struct beyn_result_t {
|
|||
complex double *eigvec; // Rows are the eigenvectors
|
||||
double *ranktest_SV;
|
||||
|
||||
/// Private, we wrap it around beyn_result_gsl_t for now.
|
||||
beyn_result_gsl_t *gsl;
|
||||
|
||||
} beyn_result_t;
|
||||
|
||||
/// Converts beyn_result_gsl_t from beyn_result_t.
|
||||
/** After calling this, use beyn_result_free() on the returned pointer;
|
||||
* do NOT run beyn_result_gsl_free() anymore.
|
||||
*/
|
||||
beyn_result_t *beyn_result_from_beyn_result_gsl(beyn_result_gsl_t *g);
|
||||
|
||||
void beyn_result_free(beyn_result_t *result);
|
||||
|
||||
beyn_result_gsl_t *beyn_solve_gsl(
|
||||
size_t m, ///< Dimension of the matrix \a M.
|
||||
size_t l, ///< Number of columns of the random matrix \f$ \hat V \f$ (larger than the expected number of solutions).
|
||||
beyn_function_M_gsl_t M, ///< Function providing the matrix \f$ M(z) \f$.
|
||||
beyn_function_M_inv_Vhat_gsl_t M_inv_Vhat, ///< Fuction providing the matrix \f$ M^{-1}(z) \hat V \f$ (optional).
|
||||
void *params, ///< Parameter pointer passed to M() and M_inv_Vhat().
|
||||
const beyn_contour_t *contour, ///< Integration contour.
|
||||
double rank_tol, ///< (default: `1e-4`) TODO DOC.
|
||||
size_t rank_min_sel, ///< Minimum number of eigenvalue candidates, even if they don't pass \a rank_tol.
|
||||
double res_tol ///< (default: `0.0`) TODO DOC.
|
||||
);
|
||||
|
||||
/// Solve a non-linear eigenproblem using Beyn's algorithm
|
||||
beyn_result_t *beyn_solve(
|
||||
size_t m, ///< Dimension of the matrix \a M.
|
||||
size_t l, ///< Number of columns of the random matrix \f$ \hat V \f$ (larger than the expected number of solutions).
|
||||
|
@ -125,7 +83,4 @@ beyn_result_t *beyn_solve(
|
|||
double res_tol ///< (default: `0.0`) TODO DOC.
|
||||
);
|
||||
|
||||
static inline complex double gsl_complex_tostd(gsl_complex z) { return GSL_REAL(z) + I*GSL_IMAG(z); }
|
||||
static inline gsl_complex gsl_complex_fromstd(complex double z) { return gsl_complex_rect(creal(z), cimag(z)); }
|
||||
|
||||
#endif // BEYN_H
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue