Compare commits

...

20 Commits

Author SHA1 Message Date
Marek Nečada 33d144cf68 Fix missing import in finiterectlat-scatter.py
continuous-integration/drone/push Build was killed Details
2023-12-26 12:35:05 +02:00
Marek Nečada 53764f3dd1 Fix qpms_vswf_set_reindex().
continuous-integration/drone/push Build is passing Details
Stupid typo with possibly serious consequences...
2022-06-23 11:34:15 +03:00
Marek Nečada f9620e1d11 Fix saving lists of arrays with recent versions of numpy 2022-06-22 12:30:02 +03:00
Marek Nečada 5e4f9130fb Disable "hard" examples in CI 2022-06-21 15:13:20 +03:00
Marek Nečada 03e5be17f9 Add bc to CI common prerequisities (required to run examples)
continuous-integration/drone/push Build was killed Details
2022-06-21 09:54:24 +03:00
Marek Nečada 74ce35605b Run some working examples in CI
continuous-integration/drone/push Build is failing Details
2022-06-21 09:41:37 +03:00
Marek Nečada 2a85b16347 sympy fix deprecated cyclic printing init
continuous-integration/drone/push Build is passing Details
2022-06-21 09:35:36 +03:00
Marek Nečada ac0d322246 Initial qpms version metadata in library and output files
continuous-integration/drone/push Build is passing Details
Merge branch 'versioning'
2022-06-21 08:53:18 +03:00
Marek Nečada a1472f3db6 Version metadata into output files
continuous-integration/drone/push Build is failing Details
2022-06-21 08:50:12 +03:00
Marek Nečada 260b053102 Fix __version__, pdf annotate function 2022-06-21 08:49:23 +03:00
Marek Nečada 78992188fd Initial version info in the C library
continuous-integration/drone/push Build is failing Details
Cmake modules taken from https://github.com/rpavlik/cmake-modules
see also https://stackoverflow.com/q/1435953
2022-06-21 06:25:22 +03:00
Marek Nečada e7f7cd38d2 Trustworthier source for zbessel submodule
continuous-integration/drone/push Build is passing Details
2022-06-16 07:41:32 +03:00
Marek Nečada b525c66043 Initial CI workflow for Drone
continuous-integration/drone/push Build is passing Details
2022-06-16 02:25:17 +03:00
Marek Nečada e69b927ec3 List of public mirrors 2022-06-10 12:43:16 +03:00
Marek Nečada 2731a87ef7 Installation on Android. 2022-06-07 07:07:37 +03:00
Marek Nečada 3a34effe34 Don't import qpms_p in __init__, remove scipy from install dependencies 2022-06-07 06:10:24 +03:00
Marek Nečada 1aac5de903 Replace scipy.constants with own constants module. 2022-06-07 05:55:36 +03:00
Marek Nečada 87c2fd24fe Use detected libraries in CMakeLists.txt instead of hardcoded ones.
Should fix some issues while building/linking libqpms.so;
still needs to be somehow done in the Python part as well.
2022-06-06 12:07:25 +03:00
Marek Nečada aea0afee15 Fix unitialised diagonal blocks in full modeproblem matrix.
The bug in qpms_scatsysw_build_modeproblem_matrix_full()
via qpms_scatsysw_scatsyswk_build_modeproblem_matrix_full()
affected finite-size arrays: instead of filling the diagonal
interaction blocks with zeros, they were filled with undefined
values from a superfluous zgemm() call.
2021-12-21 11:36:58 +02:00
Kristian Arjas 77a3566aba Fix MaterialInterpolator memory issue 2021-10-27 23:51:54 +03:00
43 changed files with 774 additions and 62 deletions

83
.drone.yml Normal file
View File

@ -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

2
.gitmodules vendored
View File

@ -1,4 +1,4 @@
[submodule "camos"]
path = camos
url = https://github.com/texnokrates/zbessel.git
url = https://codeberg.org/QPMS/zbessel.git
branch = purec

View File

@ -10,7 +10,7 @@ include(GNUInstallDirs)
project (QPMS)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
macro(use_c99)
if (CMAKE_VERSION VERSION_LESS "3.1")

View File

@ -753,7 +753,7 @@ WARN_LOGFILE =
# spaces.
# Note: If this tag is empty the current directory is searched.
INPUT = qpms notes misc finite_systems.md CLIUTILS.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

14
MIRRORS.md Normal file
View File

@ -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

View File

@ -1,7 +1,9 @@
[![Build Status](https://drone.perkele.eu/api/badges/QPMS/qpms/status.svg)](https://drone.perkele.eu/QPMS/qpms)
QPMS README
===========
QPMS (standing for QPMS Photonic Multiple Scattering)
[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
@ -43,7 +45,8 @@ Infinite systems (lattices)
Getting the code
================
The main upstream public repository is located at <https://repo.or.cz/qpms.git>.
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.
@ -89,14 +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.
@ -166,12 +176,13 @@ 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/
@ -180,3 +191,4 @@ in Telegram!
[telegramchat]: https://t.me/QPMScattering
[authormail]: mailto:marek@necada.org
[cliutils]: CLIUTILS.md
[MIRRORS]: MIRRORS.md

7
ci/00_make_dockerfiles.sh Executable file
View File

@ -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

5
ci/01_make_buildenv_images.sh Executable file
View File

@ -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 .

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,3 @@
FROM commondeps AS numlibs
# openblas-dev adds gfortran :(
RUN apk add openblas-dev gsl-dev

View File

@ -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

View File

@ -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

View File

@ -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

1
ci/drone.yml Symbolic link
View File

@ -0,0 +1 @@
../.drone.yml

View File

@ -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()

View File

@ -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()

23
cmake/LICENSE_1_0.txt Normal file
View File

@ -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.

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import math
from qpms.argproc import ArgParser, make_dict_action, sslice
from qpms.argproc import ArgParser, make_dict_action, sslice, annotate_pdf_metadata
figscale=3
ap = ArgParser(['rectlattice2d_finite', 'single_particle', 'single_lMax', 'single_omega'])
@ -44,7 +44,7 @@ import numpy as np
import qpms
from qpms.cybspec import BaseSpec
from qpms.cytmatrices import CTMatrix, TMatrixGenerator
from qpms.qpms_c import Particle
from qpms.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
@ -225,7 +225,7 @@ for iri in range(ss.nirreps):
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),
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],
@ -251,10 +251,10 @@ if not math.isnan(a.ccd_distance):
logging.info("Far fields done")
outfile = defaultprefix + ".npz" if a.output is None else a.output
np.savez(outfile, meta=vars(a),
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 = scattered_ir,
scattered_ir_packed = np.array(scattered_ir, dtype=np.object),
scattered_full = scattered_full,
ir_contained = ir_contained,
t=t, l=l, m=m,
@ -355,6 +355,7 @@ if a.plot or (a.plot_out is not None):
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)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import math
from qpms.argproc import ArgParser
from qpms.argproc import ArgParser, annotate_pdf_metadata
ap = ArgParser(['rectlattice2d_finite', 'background_analytical', 'single_particle', 'single_lMax', ])
@ -100,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)
@ -110,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}$')
@ -119,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)

View File

@ -1,8 +1,8 @@
#!/usr/bin/env python3
from qpms.argproc import ArgParser, annotate_pdf_metadata
import math
pi = math.pi
from qpms.argproc import ArgParser
ap = ArgParser(['rectlattice2d_finite', 'single_particle', 'single_lMax', 'omega_seq_real_ng', 'planewave'])
@ -111,7 +111,7 @@ for i, omega in enumerate(ap.allomegas):
σ_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), omega=omega, k_sph=k_sph_list, k_cart = k_cart_arr, E_cart=E_cart_list, E_sph=np.array(E_sph),
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)
@ -122,7 +122,8 @@ for i, omega in enumerate(ap.allomegas):
outfile = defaultprefix + ".npz" if a.output is None else a.output
np.savez(outfile, meta=vars(a), k_sph=k_sph_list, k_cart = k_cart_arr, E_cart=E_cart_list, E_sph=np.array(E_sph),
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
)
@ -231,6 +232,7 @@ if a.plot or (a.plot_out is not None):
pdf.savefig(fig)
plt.close(fig)
annotate_pdf_metadata(pdf, scriptname="finiterectlat-scatter.py")
exit(0)

View File

@ -1,7 +1,7 @@
#!/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', 'omega_seq'])
ap.add_argument("-o", "--output", type=str, required=False, help='output path (if not provided, will be generated automatically)')
@ -93,7 +93,7 @@ for i, omega in enumerate(omegas):
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), 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
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)
@ -102,7 +102,8 @@ 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']()
@ -117,9 +118,11 @@ if a.plot or (a.plot_out is not None):
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
fig.savefig(plotfile)
with PdfPages(plotfile) as pdf:
pdf.savefig(fig)
annotate_pdf_metadata(pdf, scriptname='infiniterectlat-k0realfreqsvd.py')
exit(0)

View File

@ -2,7 +2,7 @@
import math
pi = math.pi
from qpms.argproc import ArgParser
from qpms.argproc import ArgParser, annotate_pdf_metadata
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)')
@ -106,7 +106,7 @@ with pgsl_ignore_error(15): # avoid gsl crashing on underflow
σ_abs_arr = σ_ext_arr - σ_scat_arr
outfile = defaultprefix + ".npz" if a.output is None else a.output
np.savez(outfile, meta=vars(a), 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
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)
@ -214,6 +214,6 @@ if a.plot or (a.plot_out is not None):
pdf.savefig(fig)
plt.close(fig)
annotate_pdf_metadata(pdf)
exit(0)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import math
from qpms.argproc import ArgParser, sfloat
from qpms.argproc import ArgParser, sfloat, annotate_pdf_metadata
ap = ArgParser(['const_real_background', 'lattice2d', 'multi_particle']) # TODO general analytical background
@ -112,7 +112,7 @@ res['inside_contour'] = inside_ellipse((res['eigval'].real, res['eigval'].imag),
#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),
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),
@ -132,6 +132,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,)
@ -155,8 +156,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='lat2d_modes.py')
exit(0)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import math
from qpms.argproc import ArgParser, sfloat
from qpms.argproc import ArgParser, sfloat, annotate_pdf_metadata
ap = ArgParser(['background', 'lattice2d', 'multi_particle', 'omega_seq'])
@ -88,7 +88,7 @@ for i, omega in enumerate(omegas):
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), 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
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)
@ -97,6 +97,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)
@ -118,9 +119,11 @@ if a.plot or (a.plot_out is not None):
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
fig.savefig(plotfile)
with PdfPages(plotfile) as pdf:
pdf.savefig(fig)
annotate_pdf_metadata(pdf, scriptname='lat2d_realfreqsvd.py')
exit(0)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import math
from qpms.argproc import ArgParser
from qpms.argproc import ArgParser, annotate_pdf_metadata
ap = ArgParser(['rectlattice2d', 'const_real_background', 'single_particle', 'single_lMax']) # const_real_background needed for calculation of the diffracted orders
ap.add_argument("-k", nargs=2, type=float, required=True, help='k vector', metavar=('K_X', 'K_Y'))
@ -116,7 +116,7 @@ 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),
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),
@ -133,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,)
@ -156,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)

107
notes/INSTALL_ANDROID.md Normal file
View File

@ -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.

View File

@ -7,15 +7,23 @@ 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()
@ -23,9 +31,9 @@ set(LIBS ${LIBS} ${GSL_LIBRARIES} ${GSLCBLAS_LIBRARIES})
target_link_libraries (qpms
gsl
lapack
blas
${GSL_LIBRARIES}
${LAPACK_LIBRARIES}
${BLAS_LIBRARIES}
${QPMS_AMOSLIB}
Faddeeva
)

View File

@ -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:

View File

@ -540,3 +540,22 @@ class ArgParser:
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)

View File

@ -1,7 +1,26 @@
# unit conversions, mostly for standalone usage
# TODO avoid importing the "heavy" qpms parts
from scipy.constants import epsilon_0 as ε_0, c, pi as π, e as eV, hbar, hbar as , mu_0 as μ_0
pi = π
"""
Constants and unit conversion, mostly for standalode usage.
Previously, QPMS used scipy.constants in the python parts.
Now the relevant ones are set explicitly here in order
to avoid dependency on the whole scipy (which needs a fortran
compiler to build.
The values are taken from scipy / "2018 CODATA recommended values".
They slightly differ from the constants in GSL that are used
in the C code. It would be desirable to use the same source,
hence the values here might be subject to change in future versions.
"""
epsilon_0 = ε_0 = 8.8541878128e-12 # ± 0.0000000013e-12 F m^-1
c = speed_of_light = 299792458.
eV = e = elementary_charge = 1.602176487e-19 # ± 0000000040e-19 C
hbar = = 1.054571800e-34 # ± 0.000000013e-34 J s
mu_0 = μ_0 = 1.25663706212e-6 # ± 0.00000000019 e-6 N A^-2
from math import pi
π = pi
μm = 1e-6
nm = 1e-9
# "SCUFF FREQUENCY UNIT"

View File

@ -18,7 +18,7 @@ cdef class MaterialInterpolator:
cdef readonly double omegamin
cdef readonly double omegamax
cdef inline void *rawpointer(self):
return <void *>&(self.interp)
return <void *>(self.interp)
cdef class EpsMu:
cdef public qpms_epsmu_t em

View File

@ -9,7 +9,7 @@ cimport cython
import enum
import warnings
import os
from scipy.constants import e as eV, hbar, c
from .constants import e as eV, hbar, c
from libc.stdlib cimport malloc, free, calloc, abort
class EpsMuGeneratorType(enum.Enum):

View File

@ -17,6 +17,9 @@ from .cymaterials cimport EpsMuGenerator, EpsMu
from libc.stdlib cimport malloc, free, calloc
import warnings
def qpms_library_version():
return "git_" + qpms_version_git_sha1.decode('utf-8')
from cython.parallel cimport prange, parallel
from cython cimport boundscheck, wraparound

View File

@ -4,6 +4,9 @@ ctypedef double complex cdouble
from libc.stdint cimport *
cdef extern from "version.h":
const char *qpms_version_git_sha1
cdef extern from "gsl/gsl_errno.h":
ctypedef void gsl_error_handler_t (const char *reason, const char *file,
int line, int gsl_errno)

View File

@ -6,7 +6,7 @@ import numpy as np
from .qpms_c import *
ň = np.newaxis
import scipy
from scipy.constants import epsilon_0 as ε_0, c, pi as π, e, hbar as , mu_0 as μ_0
from .constants import ε_0, c, pi, π, e, , μ_0
eV = e
from scipy.special import lpmn, lpmv, spherical_jn, spherical_yn, poch, gammaln, factorial
import math

View File

@ -1295,7 +1295,6 @@ static inline complex double *qpms_scatsysw_scatsyswk_build_modeproblem_matrix_f
QPMS_CRASHING_MALLOC(target, SQ(full_len) * sizeof(complex double));
complex double *tmp; // translation matrix, S or W
QPMS_CRASHING_MALLOC(tmp, SQ(ss->max_bspecn) * sizeof(complex double));
memset(target, 0, SQ(full_len) * sizeof(complex double));
const complex double zero = 0, minusone = -1;
{ // Non-diagonal part; M[piR, piC] = -T[piR] S(piR<-piC)
size_t fullvec_offsetR = 0;
@ -1321,7 +1320,14 @@ static inline complex double *qpms_scatsysw_scatsyswk_build_modeproblem_matrix_f
QPMS_EWALD_FULL, eta));
}
cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
if (k == NULL && piC == piR) {
// non-periodic case diagonal block: no "self-interaction", just
// fill with zeroes (the ones on the diagonal are added in the very end)
QPMS_ENSURE_SUCCESS(LAPACKE_zlaset(CblasRowMajor, 'x',
bspecR->n /*m*/, bspecC->n/*n*/, 0 /*alfa: offdiag*/, 0 /*beta: diag*/,
target + fullvec_offsetR*full_len + fullvec_offsetC /*a*/,
full_len /*lda*/));
} else cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
bspecR->n /*m*/, bspecC->n /*n*/, bspecR->n /*k*/,
&minusone/*alpha*/, tmmR/*a*/, bspecR->n/*lda*/,
tmp/*b*/, bspecC->n/*ldb*/, &zero/*beta*/,

View File

@ -1,5 +1,6 @@
import sympy
from sympy.combinatorics import Permutation, PermutationGroup
Permutation.print_cyclic = True
sympy.init_printing(perm_cyclic = True)
import cmath
from cmath import exp, pi
from math import sqrt

View File

@ -12,8 +12,7 @@ except ImportError:
use_moble_quaternion = False
import re
from scipy import interpolate
from scipy.constants import hbar, e as eV, pi, c
from .constants import hbar, eV, pi, c
from .cycommon import get_mn_y, get_nelem
from .cyquaternions import CQuat
ň = np.newaxis
@ -440,6 +439,7 @@ class TMatrix(TMatrixSpec):
TODO support for different/multiple interpolators
'''
def __init__(self, tmatrix_spec):
from scipy import interpolate
#self.specification = tmatrix_spec
self.lMax_override = tmatrix_spec.lMax_override
self.tmatrix_path = tmatrix_spec.tmatrix_path

2
qpms/version.c.in Normal file
View File

@ -0,0 +1,2 @@
#define QPMS_GIT_SHA1 "@GIT_SHA1@"
const char qpms_version_git_sha1[] = QPMS_GIT_SHA1;

4
qpms/version.h Normal file
View File

@ -0,0 +1,4 @@
#ifndef QPMS_VERSION_H
#define QPMS_VERSION_H
extern const char qpms_version_git_sha1[];
#endif //QPMS_VERSION_H

View File

@ -131,7 +131,7 @@ size_t *qpms_vswf_set_reindex(const qpms_vswf_set_spec_t *small, const qpms_vswf
while(big_pairs[bi].ui < small_pairs[si].ui)
++bi;
if(big_pairs[bi].ui == small_pairs[si].ui)
r[small_pairs[si].i_orig] = big_pairs[si].i_orig;
r[small_pairs[si].i_orig] = big_pairs[bi].i_orig;
else
r[small_pairs[si].i_orig] = ~(size_t)0;
}

View File

@ -161,7 +161,7 @@ setup(name='qpms',
setup_requires=['cython>=0.28','numpy>=1.2','setuptools>=18.0'],
install_requires=['cython>=0.28',
#'quaternion','spherical_functions',
'scipy>=0.18.0', 'sympy>=1.2', 'numpy>=1.2'],
'sympy>=1.2', 'numpy>=1.2'],
#dependency_links=['https://github.com/moble/quaternion/archive/v2.0.tar.gz','https://github.com/moble/spherical_functions/archive/master.zip'],
ext_modules=cythonize([qpms_c, cywaves, cytranslations, cytmatrices, cycommon, cyquaternions, cybspec, cymaterials, cyewaldtest], include_path=['qpms', 'amos'], gdb_debug=True),
cmdclass = {'build_ext': build_ext},