diff --git a/.github/workflows/phono3py-pytest-conda-mkl-phphmtblas.yml b/.github/workflows/phono3py-pytest-conda-mkl-phphmtblas.yml index 36bc64eb..f8c54bed 100644 --- a/.github/workflows/phono3py-pytest-conda-mkl-phphmtblas.yml +++ b/.github/workflows/phono3py-pytest-conda-mkl-phphmtblas.yml @@ -24,8 +24,7 @@ jobs: run: | conda activate test conda install --yes python=${{ matrix.python-version }} - #conda install --yes matplotlib-base pyyaml "libblas=*=*openblas" openblas h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler - conda install --yes matplotlib-base pyyaml "libblas=*=*mkl" mkl-include h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler + conda install --yes matplotlib-base pyyaml "libblas=*=*mkl" mkl-include h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler cxx-compiler - name: Install symfc develop branch run: | conda activate test @@ -38,12 +37,12 @@ jobs: conda activate test git clone --depth 1 https://github.com/phonopy/phonopy.git cd phonopy - PHONOPY_USE_OPENMP=true pip install -e . -vvv + pip install -e . -vvv cd .. - name: Install phono3py run: | conda activate test - PHPHCALC_USE_MTBLAS=true pip install -e . -vvv + PHPHCALC_USE_MTBLAS=ON pip install -e . -vvv - name: Run pytest run: | pytest -v --cov=./ --cov-report=xml test diff --git a/.github/workflows/phono3py-pytest-conda-mkl-v2.yml b/.github/workflows/phono3py-pytest-conda-mkl-v2.yml index 4e755b19..91c32ee9 100644 --- a/.github/workflows/phono3py-pytest-conda-mkl-v2.yml +++ b/.github/workflows/phono3py-pytest-conda-mkl-v2.yml @@ -24,8 +24,7 @@ jobs: run: | conda activate test conda install --yes python=${{ matrix.python-version }} - #conda install --yes matplotlib-base pyyaml "libblas=*=*openblas" openblas h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler - conda install --yes matplotlib-base pyyaml "libblas=*=*mkl" mkl-include h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler + conda install --yes matplotlib-base pyyaml "libblas=*=*mkl" mkl-include h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler cxx-compiler - name: Install symfc develop branch run: | conda activate test @@ -38,7 +37,7 @@ jobs: conda activate test git clone --depth 1 https://github.com/phonopy/phonopy.git cd phonopy - PHONOPY_USE_OPENMP=true pip install -e . -vvv + pip install -e . -vvv cd .. - name: Install phono3py run: | diff --git a/.github/workflows/phono3py-pytest-conda-mkl.yml b/.github/workflows/phono3py-pytest-conda-mkl.yml index 486af093..72616e31 100644 --- a/.github/workflows/phono3py-pytest-conda-mkl.yml +++ b/.github/workflows/phono3py-pytest-conda-mkl.yml @@ -24,8 +24,7 @@ jobs: run: | conda activate test conda install --yes python=${{ matrix.python-version }} - #conda install --yes matplotlib-base pyyaml "libblas=*=*openblas" openblas h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler - conda install --yes matplotlib-base pyyaml "libblas=*=*mkl" mkl-include h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler + conda install --yes matplotlib-base pyyaml "libblas=*=*mkl" mkl-include h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler cxx-compiler - name: Install symfc develop branch run: | conda activate test @@ -38,7 +37,7 @@ jobs: conda activate test git clone --depth 1 https://github.com/phonopy/phonopy.git cd phonopy - PHONOPY_USE_OPENMP=true pip install -e . -vvv + pip install -e . -vvv cd .. - name: Install phono3py run: | diff --git a/.github/workflows/phono3py-pytest-conda-numpy2.yml b/.github/workflows/phono3py-pytest-conda-numpy2.yml index cc1798ff..92f010cd 100644 --- a/.github/workflows/phono3py-pytest-conda-numpy2.yml +++ b/.github/workflows/phono3py-pytest-conda-numpy2.yml @@ -24,7 +24,7 @@ jobs: run: | conda activate test conda install --yes python=${{ matrix.python-version }} - conda install --yes matplotlib-base pyyaml "libblas=*=*openblas" openblas h5py "numpy=2" scipy pytest codecov pytest-cov cmake c-compiler + conda install --yes matplotlib-base pyyaml "libblas=*=*openblas" openblas h5py "numpy=2" scipy pytest codecov pytest-cov cmake c-compiler cxx-compiler - name: Install spglib develop branch run: | conda activate test @@ -44,7 +44,7 @@ jobs: conda activate test git clone --depth 1 https://github.com/phonopy/phonopy.git cd phonopy - PHONOPY_USE_OPENMP=true pip install -e . -vvv + pip install -e . -vvv cd .. - name: Install phono3py run: | diff --git a/.github/workflows/phono3py-pytest-conda-phphmtblas.yml b/.github/workflows/phono3py-pytest-conda-phphmtblas.yml index 5d6aac02..37473838 100644 --- a/.github/workflows/phono3py-pytest-conda-phphmtblas.yml +++ b/.github/workflows/phono3py-pytest-conda-phphmtblas.yml @@ -24,8 +24,7 @@ jobs: run: | conda activate test conda install --yes python=${{ matrix.python-version }} - conda install --yes matplotlib-base pyyaml "libblas=*=*openblas" openblas h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler - #conda install --yes matplotlib-base pyyaml "libblas=*=*mkl" mkl-include h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler + conda install --yes matplotlib-base pyyaml "libblas=*=*openblas" openblas h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler cxx-compiler - name: Install symfc develop branch run: | conda activate test @@ -38,12 +37,12 @@ jobs: conda activate test git clone --depth 1 https://github.com/phonopy/phonopy.git cd phonopy - PHONOPY_USE_OPENMP=true pip install -e . -vvv + pip install -e . -vvv cd .. - name: Install phono3py run: | conda activate test - PHPHCALC_USE_MTBLAS=true pip install -e . -vvv + PHPHCALC_USE_MTBLAS=ON pip install -e . -vvv - name: Run pytest run: | pytest -v --cov=./ --cov-report=xml test diff --git a/.github/workflows/phono3py-pytest-conda.yml b/.github/workflows/phono3py-pytest-conda.yml index 05eb347b..e9f0f1e2 100644 --- a/.github/workflows/phono3py-pytest-conda.yml +++ b/.github/workflows/phono3py-pytest-conda.yml @@ -24,14 +24,13 @@ jobs: run: | conda activate test conda install --yes python=${{ matrix.python-version }} - conda install --yes matplotlib-base pyyaml "libblas=*=*openblas" openblas h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler - #conda install --yes matplotlib-base pyyaml "libblas=*=*mkl" mkl-include h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler + conda install --yes matplotlib-base pyyaml "libblas=*=*openblas" openblas h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler cxx-compiler - name: Install phonopy develop branch run: | conda activate test git clone --depth 1 https://github.com/phonopy/phonopy.git cd phonopy - PHONOPY_USE_OPENMP=true pip install -e . -vvv + pip install -e . -vvv cd .. - name: Install phono3py run: | diff --git a/.github/workflows/publish-to-test-pypi.yml b/.github/workflows/publish-to-test-pypi.yml index 64a45448..65606fbe 100644 --- a/.github/workflows/publish-to-test-pypi.yml +++ b/.github/workflows/publish-to-test-pypi.yml @@ -9,30 +9,21 @@ on: jobs: build-linux: runs-on: ubuntu-latest - defaults: - run: - shell: bash -l {0} strategy: matrix: - python-version: ["3.10", ] + python-version: [3.12, ] steps: - uses: actions/checkout@v4 - # Use conda-incubator/setup-miniconda for precise control of conda infrastructure - - uses: conda-incubator/setup-miniconda@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 with: - auto-update-conda: true - channels: conda-forge - channel-priority: strict python-version: ${{ matrix.python-version }} - name: Make sdist run: | - conda activate test - conda install --yes python=${{ matrix.python-version }} - conda install --yes "libblas=*=*openblas" openblas cmake c-compiler numpy - ./get_nanoversion.sh - cat __nanoversion__.txt - python setup.py sdist + git tag v`grep __version__ phono3py/version.py|awk -F'"' '{print($2)}'` + pip install build + python -m build --sdist - name: Publish package to TestPyPI if: github.event_name == 'push' && startsWith(github.ref, 'refs/heads/rc') uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5da3a44d..4e7888ba 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ repos: - id: check-added-large-files - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.10 + rev: v0.5.0 hooks: - id: ruff args: [ "--fix", "--show-fixes" ] diff --git a/CMakeLists.txt b/CMakeLists.txt index 23c842eb..fc372955 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,304 +1,398 @@ -cmake_minimum_required(VERSION 3.15) -project(phono3py C) +cmake_minimum_required(VERSION 3.20) -option(PHPHCALC "Option to build phph calculation module" OFF) -option(PHONONCALC "Option to build phonon calculation module" OFF) -option(GRIDSYS "Option to build gridsys module" OFF) -option(WITH_Fortran "enable fortran interface" OFF) +option(BUILD_PHPHCALC_LIB "Option to build phph calculation module" OFF) +option(BUILD_PHONONCALC_LIB "Option to build phonon calculation module" OFF) +option(BUILD_GRIDSYS_LIB "Option to build gridsys module" OFF) +option(PHONO3PY_WITH_Fortran "enable fortran interface" OFF) option(PHONO3PY_USE_OMP "Option to search OpenMP library" ON) -option(PHPHCALC_USE_MTBLAS "Use multithread BLAS is it exists" OFF) -option(WITH_TESTS "build unit tests" OFF) -option(BUILD_SHARED_LIBRARIES "Option to build shared library" OFF) -if(WITH_Fortran) - enable_language(Fortran) - set(GRIDSYS ON) +option(PHONO3PY_USE_MTBLAS "Use multithread BLAS if it exists" ON) +option(PHONO3PY_WITH_TESTS "build unit tests" OFF) +option(BUILD_SHARED_LIBS "Option to build shared library" OFF) + +if(PHONO3PY_WITH_Fortran) + enable_language(Fortran) + set(BUILD_GRIDSYS_LIB ON) endif() -if(WITH_TESTS) - set(BUILD_SHARED_LIBRARIES ON) - set(GRIDSYS ON) + +if(PHONO3PY_WITH_TESTS) + set(BUILD_SHARED_LIBS ON) + set(BUILD_GRIDSYS_LIB ON) endif() -set(CMAKE_MACOSX_RPATH 1) -set(CMAKE_C_FLAGS_RELEASE "-Wall -O2") -set(CMAKE_C_FLAGS_DEBUG "-g -DLAGWARNING -DTHMWARNING") +if((NOT BUILD_PHPHCALC_LIB) + AND (NOT BUILD_PHONONCALC_LIB) + AND (NOT BUILD_GRIDSYS_LIB)) + set(BUILD_NANOBIND_MODULE ON) + message(STATUS "Build nanobind module of ${SKBUILD_PROJECT_NAME}") +else() + set(BUILD_NANOBIND_MODULE OFF) +endif() -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) -endif(NOT CMAKE_BUILD_TYPE) +if(BUILD_NANOBIND_MODULE) + project(${SKBUILD_PROJECT_NAME}) + set(DEV_MODULE Development.Module) + find_package( + Python 3.8 REQUIRED + COMPONENTS Interpreter ${DEV_MODULE} + OPTIONAL_COMPONENTS Development.SABIModule) +else() + project(phono3py C) + set(CMAKE_MACOSX_RPATH 1) + set(CMAKE_C_FLAGS_RELEASE "-Wall -O2") + set(CMAKE_C_FLAGS_DEBUG "-g -DLAGWARNING -DTHMWARNING") + + # Version numbers + file(READ ${PROJECT_SOURCE_DIR}/phono3py/version.py version_file) + string(REGEX MATCH "__version__.*([0-9]+)[.]([0-9]+)[.]([0-9]+)" + phono3py_version ${version_file}) + set(MAJOR_VERSION ${CMAKE_MATCH_1}) + set(MINOR_VERSION ${CMAKE_MATCH_2}) + set(MICRO_VERSION ${CMAKE_MATCH_3}) + set(SERIAL "${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}") + set(SOSERIAL "1") + include(GNUInstallDirs) +endif() + +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE + Release + CACHE STRING "Choose the type of build." FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" + "MinSizeRel" "RelWithDebInfo") +endif() message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") message(STATUS "CMAKE_SYSTEM_PREFIX_PATH: ${CMAKE_SYSTEM_PREFIX_PATH}") -include(GNUInstallDirs) - -# set(CMAKE_POSITION_INDEPENDENT_CODE ON) - -# Version numbers -file(READ ${PROJECT_SOURCE_DIR}/phono3py/version.py version_file) -string(REGEX MATCH "__version__.*([0-9]+)[.]([0-9]+)[.]([0-9]+)" - phono3py_version ${version_file}) -set(MAJOR_VERSION ${CMAKE_MATCH_1}) -set(MINOR_VERSION ${CMAKE_MATCH_2}) -set(MICRO_VERSION ${CMAKE_MATCH_3}) -set(SERIAL "${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}") -set(SOSERIAL "1") - -if(USE_CONDA_PATH) - message(STATUS "$ENV{CONDA_PREFIX}") - set(CMAKE_MODULE_PATH $ENV{CONDA_PREFIX}) - set(MY_INCLUDES $ENV{CONDA_PREFIX}/include ${PROJECT_SOURCE_DIR}/c) - link_directories($ENV{CONDA_PREFIX}/lib) +if(USE_CONDA_PATH AND DEFINED ENV{CONDA_PREFIX}) + message(STATUS "$ENV{CONDA_PREFIX}") + set(CMAKE_MODULE_PATH $ENV{CONDA_PREFIX}) + set(MY_INCLUDES $ENV{CONDA_PREFIX}/include ${PROJECT_SOURCE_DIR}/c) + link_directories($ENV{CONDA_PREFIX}/lib) else() - set(MY_INCLUDES ${PROJECT_SOURCE_DIR}/c) + set(MY_INCLUDES ${PROJECT_SOURCE_DIR}/c) endif() if(PHONO3PY_USE_OMP) - message(STATUS "Find OpenMP library") - find_package(OpenMP) + message(STATUS "Find OpenMP library") + find_package(OpenMP) - if(OpenMP_FOUND) - message(STATUS "OpenMP libs: ${OpenMP_C_LIBRARIES}") - message(STATUS "OpenMP flags: ${OpenMP_C_FLAGS}") - endif() + if(OpenMP_FOUND) + message(STATUS "OpenMP libs: ${OpenMP_C_LIBRARIES}") + message(STATUS "OpenMP flags: ${OpenMP_C_FLAGS}") + endif() +else() + message(STATUS "OpenMP is not used.") + set(OpenMP_FOUND OFF) # cmake-lint: disable=C0103 endif() -if(PHPHCALC OR PHONONCALC) - find_package(BLAS REQUIRED) # set BLAS_LIBRARIES - - if(BLAS_FOUND) - message(STATUS "BLAS libs: ${BLAS_LIBRARIES}") - message(STATUS "BLAS flags: ${BLAS_LINKER_FLAGS}") - endif() - - find_package(LAPACK REQUIRED) # set LAPACK_LIBRARIES - - if(LAPACK_FOUND) - message(STATUS "LAPACK libs: ${LAPACK_LIBRARIES}") - message(STATUS "LAPACK flags: ${LAPACK_LINKER_FLAGS}") - endif() -endif() +if(BUILD_PHPHCALC_LIB + OR BUILD_PHONONCALC_LIB + OR BUILD_NANOBIND_MODULE) + find_package(BLAS REQUIRED) # set BLAS_LIBRARIES -if(PHPHCALC OR PHONONCALC) - if(BLAS_LIBRARIES MATCHES "libmkl") - message(STATUS "MKL detected: Set C-macros MKL_LAPACKE MULTITHREADED_BLAS") - message(STATUS "Use multithreaded BLAS for phonon calculation.") - if(PHPHCALC_USE_MTBLAS) - message(STATUS "Use multithreaded BLAS for ph-ph calculation.") + if(BLAS_FOUND) + message(STATUS "BLAS libs: ${BLAS_LIBRARIES}") + message(STATUS "BLAS flags: ${BLAS_LINKER_FLAGS}") endif() - endif() - if(BLAS_LIBRARIES MATCHES "libopenblas") - message(STATUS "OpenBLAS detected: Set C-macro MULTITHREADED_BLAS") - message(STATUS "Use multithreaded BLAS for phonon calculation.") - if(PHPHCALC_USE_MTBLAS) - message(STATUS "Use multithreaded BLAS for ph-ph calculation.") - endif() - endif() -endif() + find_package(LAPACK REQUIRED) # set LAPACK_LIBRARIES -# ############################################################################## -# phono3py # -# ############################################################################## -if(PHPHCALC) - # Source code - set(SOURCES_PHPHCALC - ${PROJECT_SOURCE_DIR}/c/bzgrid.c - ${PROJECT_SOURCE_DIR}/c/collision_matrix.c - ${PROJECT_SOURCE_DIR}/c/fc3.c - ${PROJECT_SOURCE_DIR}/c/grgrid.c - ${PROJECT_SOURCE_DIR}/c/imag_self_energy_with_g.c - ${PROJECT_SOURCE_DIR}/c/interaction.c - ${PROJECT_SOURCE_DIR}/c/isotope.c - ${PROJECT_SOURCE_DIR}/c/lagrid.c - ${PROJECT_SOURCE_DIR}/c/lapack_wrapper.c - ${PROJECT_SOURCE_DIR}/c/phono3py.c - ${PROJECT_SOURCE_DIR}/c/phonoc_utils.c - ${PROJECT_SOURCE_DIR}/c/pp_collision.c - ${PROJECT_SOURCE_DIR}/c/real_self_energy.c - ${PROJECT_SOURCE_DIR}/c/real_to_reciprocal.c - ${PROJECT_SOURCE_DIR}/c/reciprocal_to_normal.c - ${PROJECT_SOURCE_DIR}/c/snf3x3.c - ${PROJECT_SOURCE_DIR}/c/tetrahedron_method.c - ${PROJECT_SOURCE_DIR}/c/triplet.c - ${PROJECT_SOURCE_DIR}/c/triplet_grid.c - ${PROJECT_SOURCE_DIR}/c/triplet_iw.c) - - if(BUILD_SHARED_LIBRARIES) - # Shared library - add_library(ph3py SHARED ${SOURCES_PHPHCALC}) - target_link_libraries(ph3py m ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES} - ${OpenMP_C_LIBRARIES}) - target_include_directories(ph3py PRIVATE ${MY_INCLUDES}) - target_compile_options(ph3py PRIVATE ${OpenMP_C_FLAGS}) + if(LAPACK_FOUND) + message(STATUS "LAPACK libs: ${LAPACK_LIBRARIES}") + message(STATUS "LAPACK flags: ${LAPACK_LINKER_FLAGS}") + endif() if(BLAS_LIBRARIES MATCHES "libmkl") - if(PHPHCALC_USE_MTBLAS) - target_compile_definitions(ph3py PRIVATE MKL_LAPACKE MULTITHREADED_BLAS - THM_EPSILON=1e-10) - else() - target_compile_definitions(ph3py PRIVATE MKL_LAPACKE THM_EPSILON=1e-10) - endif() + message(STATUS "MKL detected: Set C-macro MKL_LAPACKE.") + + if(PHONO3PY_USE_MTBLAS) + message( + STATUS "Set C-macro MULTITHREADED_BLAS to avoid nested OpenMP calls." + ) + endif() endif() if(BLAS_LIBRARIES MATCHES "libopenblas") - if(PHPHCALC_USE_MTBLAS) - target_compile_definitions(ph3py PRIVATE MULTITHREADED_BLAS - THM_EPSILON=1e-10) - else() - target_compile_definitions(ph3py PRIVATE THM_EPSILON=1e-10) - endif() - endif() + message(STATUS "OpenBLAS detected.") - set_property(TARGET ph3py PROPERTY VERSION ${SERIAL}) - set_property(TARGET ph3py PROPERTY SOVERSION ${SOSERIAL}) - install(TARGETS ph3py LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) - endif() - - # Static link library - add_library(ph3py_static STATIC ${SOURCES_PHPHCALC}) - target_link_libraries(ph3py_static m ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES} - ${OpenMP_C_LIBRARIES}) - target_include_directories(ph3py_static PRIVATE ${MY_INCLUDES}) - target_compile_options(ph3py_static PRIVATE ${OpenMP_C_FLAGS}) - - if(BLAS_LIBRARIES MATCHES "libmkl") - if(PHPHCALC_USE_MTBLAS) - target_compile_definitions( - ph3py_static PRIVATE MKL_LAPACKE MULTITHREADED_BLAS THM_EPSILON=1e-10) - else() - target_compile_definitions(ph3py_static PRIVATE MKL_LAPACKE - THM_EPSILON=1e-10) + if(PHONO3PY_USE_MTBLAS) + message( + STATUS "Set C-macro MULTITHREADED_BLAS to avoid nested OpenMP calls." + ) + endif() endif() - endif() +endif() - if(BLAS_LIBRARIES MATCHES "libopenblas") - if(PHPHCALC_USE_MTBLAS) - target_compile_definitions(ph3py_static PRIVATE MULTITHREADED_BLAS - THM_EPSILON=1e-10) +# ################################################################################### +# Build phphcalc module # +# ################################################################################### +if(BUILD_PHPHCALC_LIB OR BUILD_NANOBIND_MODULE) + # Source code + set(SOURCES_PHPHCALC + ${PROJECT_SOURCE_DIR}/c/bzgrid.c + ${PROJECT_SOURCE_DIR}/c/collision_matrix.c + ${PROJECT_SOURCE_DIR}/c/fc3.c + ${PROJECT_SOURCE_DIR}/c/grgrid.c + ${PROJECT_SOURCE_DIR}/c/imag_self_energy_with_g.c + ${PROJECT_SOURCE_DIR}/c/interaction.c + ${PROJECT_SOURCE_DIR}/c/isotope.c + ${PROJECT_SOURCE_DIR}/c/lagrid.c + ${PROJECT_SOURCE_DIR}/c/lapack_wrapper.c + ${PROJECT_SOURCE_DIR}/c/phono3py.c + ${PROJECT_SOURCE_DIR}/c/phonoc_utils.c + ${PROJECT_SOURCE_DIR}/c/pp_collision.c + ${PROJECT_SOURCE_DIR}/c/real_self_energy.c + ${PROJECT_SOURCE_DIR}/c/real_to_reciprocal.c + ${PROJECT_SOURCE_DIR}/c/reciprocal_to_normal.c + ${PROJECT_SOURCE_DIR}/c/snf3x3.c + ${PROJECT_SOURCE_DIR}/c/tetrahedron_method.c + ${PROJECT_SOURCE_DIR}/c/triplet.c + ${PROJECT_SOURCE_DIR}/c/triplet_grid.c + ${PROJECT_SOURCE_DIR}/c/triplet_iw.c) + + if(BUILD_SHARED_LIBS) + # Shared library + add_library(phphcalc_lib SHARED ${SOURCES_PHPHCALC}) + + if(OpenMP_FOUND) + target_link_libraries(phphcalc_lib PRIVATE BLAS::BLAS LAPACK::LAPACK + OpenMP::OpenMP_C) + else() + target_link_libraries(phphcalc_lib PRIVATE BLAS::BLAS LAPACK::LAPACK) + endif() + + target_include_directories(phphcalc_lib PRIVATE ${MY_INCLUDES}) + + if(BLAS_LIBRARIES MATCHES "libmkl") + if(PHONO3PY_USE_MTBLAS) + target_compile_definitions( + phphcalc_lib PRIVATE MKL_LAPACKE MULTITHREADED_BLAS + THM_EPSILON=1e-10) + else() + target_compile_definitions(phphcalc_lib PRIVATE MKL_LAPACKE + THM_EPSILON=1e-10) + endif() + endif() + + if(BLAS_LIBRARIES MATCHES "libopenblas") + if(PHONO3PY_USE_MTBLAS) + target_compile_definitions(phphcalc_lib PRIVATE MULTITHREADED_BLAS + THM_EPSILON=1e-10) + else() + target_compile_definitions(phphcalc_lib PRIVATE THM_EPSILON=1e-10) + endif() + endif() else() - target_compile_definitions(ph3py_static PRIVATE THM_EPSILON=1e-10) + # Static link library + add_library(phphcalc_lib STATIC ${SOURCES_PHPHCALC}) + + if(OpenMP_FOUND) + target_link_libraries(phphcalc_lib BLAS::BLAS LAPACK::LAPACK + OpenMP::OpenMP_C) + else() + target_link_libraries(phphcalc_lib BLAS::BLAS LAPACK::LAPACK) + endif() + + target_include_directories(phphcalc_lib PRIVATE ${MY_INCLUDES}) + + if(BLAS_LIBRARIES MATCHES "libmkl") + if(PHONO3PY_USE_MTBLAS) + target_compile_definitions( + phphcalc_lib PRIVATE MKL_LAPACKE MULTITHREADED_BLAS + THM_EPSILON=1e-10) + else() + target_compile_definitions(phphcalc_lib PRIVATE MKL_LAPACKE + THM_EPSILON=1e-10) + endif() + endif() + + if(BLAS_LIBRARIES MATCHES "libopenblas") + if(PHONO3PY_USE_MTBLAS) + target_compile_definitions(phphcalc_lib PRIVATE MULTITHREADED_BLAS + THM_EPSILON=1e-10) + else() + target_compile_definitions(phphcalc_lib PRIVATE THM_EPSILON=1e-10) + endif() + endif() endif() - endif() - - set_property(TARGET ph3py_static PROPERTY VERSION ${SERIAL}) - set_property(TARGET ph3py_static PROPERTY SOVERSION ${SOSERIAL}) - set_property(TARGET ph3py_static PROPERTY OUTPUT_NAME ph3py) - install(TARGETS ph3py_static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - # Header file - install(FILES ${PROJECT_SOURCE_DIR}/c/phono3py.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + if(NOT BUILD_NANOBIND_MODULE) + if(BUILD_SHARED_LIBS) + set_property(TARGET phphcalc_lib PROPERTY VERSION ${SERIAL}) + set_property(TARGET phphcalc_lib PROPERTY SOVERSION ${SOSERIAL}) + install(TARGETS phphcalc_lib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) + else() + set_property(TARGET phphcalc_lib PROPERTY VERSION ${SERIAL}) + set_property(TARGET phphcalc_lib PROPERTY SOVERSION ${SOSERIAL}) + set_property(TARGET phphcalc_lib PROPERTY OUTPUT_NAME phphcalc_lib) + install(TARGETS phphcalc_lib ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() + + # Header file + install(FILES ${PROJECT_SOURCE_DIR}/c/phono3py.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + endif() endif() -# ############################################################################## +# ################################################################################### # phononcalc # -# ############################################################################## -if(PHONONCALC) - # Source code - set(SOURCES_PHONONCALC - ${PROJECT_SOURCE_DIR}/c/dynmat.c ${PROJECT_SOURCE_DIR}/c/lapack_wrapper.c - ${PROJECT_SOURCE_DIR}/c/phonon.c ${PROJECT_SOURCE_DIR}/c/phononcalc.c) - - if(BUILD_SHARED_LIBRARIES) - # Shared library - add_library(phcalc SHARED ${SOURCES_PHONONCALC}) - target_link_libraries(phcalc m ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES} - ${OpenMP_C_LIBRARIES}) - target_include_directories(phcalc PRIVATE ${MY_INCLUDES}) - target_compile_options(phcalc PRIVATE ${OpenMP_C_FLAGS}) +# ################################################################################### +if(BUILD_PHONONCALC_LIB OR BUILD_NANOBIND_MODULE) + # Source code + set(SOURCES_PHONONCALC + ${PROJECT_SOURCE_DIR}/c/dynmat.c ${PROJECT_SOURCE_DIR}/c/lapack_wrapper.c + ${PROJECT_SOURCE_DIR}/c/phonon.c ${PROJECT_SOURCE_DIR}/c/phononcalc.c) + + if(BUILD_SHARED_LIBS) + # Shared library + add_library(phononcalc_lib SHARED ${SOURCES_PHONONCALC}) + + if(OpenMP_FOUND) + target_link_libraries(phononcalc_lib BLAS::BLAS LAPACK::LAPACK + OpenMP::OpenMP_C) + else() + target_link_libraries(phononcalc_lib BLAS::BLAS LAPACK::LAPACK) + endif() + + target_include_directories(phononcalc_lib PRIVATE ${MY_INCLUDES}) + + if(BLAS_LIBRARIES MATCHES "libmkl") + target_compile_definitions(phononcalc_lib PRIVATE MKL_LAPACKE + MULTITHREADED_BLAS) + endif() + + if(BLAS_LIBRARIES MATCHES "libopenblas") + target_compile_definitions(phononcalc_lib PRIVATE MULTITHREADED_BLAS) + endif() - if(BLAS_LIBRARIES MATCHES "libmkl") - target_compile_definitions(phcalc PRIVATE MKL_LAPACKE MULTITHREADED_BLAS) + else() + # Static link library + add_library(phononcalc_lib STATIC ${SOURCES_PHONONCALC}) + + if(OpenMP_FOUND) + target_link_libraries(phononcalc_lib PRIVATE BLAS::BLAS LAPACK::LAPACK + OpenMP::OpenMP_C) + else() + target_link_libraries(phononcalc_lib PRIVATE BLAS::BLAS LAPACK::LAPACK) + endif() + + target_include_directories(phononcalc_lib PRIVATE ${MY_INCLUDES}) + + if(BLAS_LIBRARIES MATCHES "libmkl") + target_compile_definitions(phononcalc_lib PRIVATE MKL_LAPACKE + MULTITHREADED_BLAS) + endif() + + if(BLAS_LIBRARIES MATCHES "libopenblas") + target_compile_definitions(phononcalc_lib PRIVATE MULTITHREADED_BLAS) + endif() endif() - if(BLAS_LIBRARIES MATCHES "libopenblas") - target_compile_definitions(phcalc PRIVATE MULTITHREADED_BLAS) + if(NOT BUILD_NANOBIND_MODULE) + if(BUILD_SHARED_LIBS) + set_property(TARGET phononcalc_lib PROPERTY VERSION ${SERIAL}) + set_property(TARGET phononcalc_lib PROPERTY SOVERSION ${SOSERIAL}) + install(TARGETS phononcalc_lib + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) + + else() + set_property(TARGET phononcalc_lib PROPERTY VERSION ${SERIAL}) + set_property(TARGET phononcalc_lib PROPERTY SOVERSION ${SOSERIAL}) + set_property(TARGET phononcalc_lib PROPERTY OUTPUT_NAME phononcalc_lib) + install(TARGETS phononcalc_lib + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() + + # Header file + install(FILES ${PROJECT_SOURCE_DIR}/c/phononcalc.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) endif() - - set_property(TARGET phcalc PROPERTY VERSION ${SERIAL}) - set_property(TARGET phcalc PROPERTY SOVERSION ${SOSERIAL}) - install(TARGETS phcalc LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) - endif() - - # Static link library - add_library(phcalc_static STATIC ${SOURCES_PHONONCALC}) - target_link_libraries(phcalc_static m ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES} - ${OpenMP_C_LIBRARIES}) - target_include_directories(phcalc_static PRIVATE ${MY_INCLUDES}) - target_compile_options(phcalc_static PRIVATE ${OpenMP_C_FLAGS}) - - if(BLAS_LIBRARIES MATCHES "libmkl") - target_compile_definitions(phcalc_static PRIVATE MKL_LAPACKE - MULTITHREADED_BLAS) - endif() - - if(BLAS_LIBRARIES MATCHES "libopenblas") - target_compile_definitions(phcalc_static PRIVATE MULTITHREADED_BLAS) - endif() - - set_property(TARGET phcalc_static PROPERTY VERSION ${SERIAL}) - set_property(TARGET phcalc_static PROPERTY SOVERSION ${SOSERIAL}) - set_property(TARGET phcalc_static PROPERTY OUTPUT_NAME phcalc) - install(TARGETS phcalc_static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - - # Header file - install(FILES ${PROJECT_SOURCE_DIR}/c/phononcalc.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) endif() -# ############################################################################## +# ################################################################################### # grid # -# ############################################################################## -if(GRIDSYS) - # Source code - set(SOURCES_GRIDSYS - ${PROJECT_SOURCE_DIR}/c/bzgrid.c - ${PROJECT_SOURCE_DIR}/c/grgrid.c - ${PROJECT_SOURCE_DIR}/c/gridsys.c - ${PROJECT_SOURCE_DIR}/c/lagrid.c - ${PROJECT_SOURCE_DIR}/c/niggli.c - ${PROJECT_SOURCE_DIR}/c/phonoc_utils.c - ${PROJECT_SOURCE_DIR}/c/snf3x3.c - ${PROJECT_SOURCE_DIR}/c/tetrahedron_method.c - ${PROJECT_SOURCE_DIR}/c/triplet.c - ${PROJECT_SOURCE_DIR}/c/triplet_grid.c - ${PROJECT_SOURCE_DIR}/c/triplet_iw.c) - - if(BUILD_SHARED_LIBRARIES) - # Shared library - add_library(gridsys SHARED ${SOURCES_GRIDSYS}) - target_link_libraries(gridsys m ${OpenMP_C_LIBRARIES}) - target_include_directories(gridsys PRIVATE ${MY_INCLUDES}) - target_compile_options(gridsys PRIVATE ${OpenMP_C_FLAGS}) - target_compile_definitions(gridsys PRIVATE THM_EPSILON=1e-10) - set_property(TARGET gridsys PROPERTY VERSION ${SERIAL}) - set_property(TARGET gridsys PROPERTY SOVERSION ${SOSERIAL}) - install(TARGETS gridsys LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) - endif() - - # Static link library - add_library(gridsys_static STATIC ${SOURCES_GRIDSYS}) - target_link_libraries(gridsys_static m ${OpenMP_C_LIBRARIES}) - target_include_directories(gridsys_static PRIVATE ${MY_INCLUDES}) - target_compile_options(gridsys_static PRIVATE ${OpenMP_C_FLAGS}) - target_compile_definitions(gridsys_static PRIVATE THM_EPSILON=1e-10) - set_property(TARGET gridsys_static PROPERTY VERSION ${SERIAL}) - set_property(TARGET gridsys_static PROPERTY SOVERSION ${SOSERIAL}) - set_property(TARGET gridsys_static PROPERTY OUTPUT_NAME gridsys) - install(TARGETS gridsys_static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - - # Header file - install(FILES ${PROJECT_SOURCE_DIR}/c/gridsys.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +# ################################################################################### +if(BUILD_GRIDSYS_LIB) + # Source code + set(SOURCES_GRIDSYS + ${PROJECT_SOURCE_DIR}/c/bzgrid.c + ${PROJECT_SOURCE_DIR}/c/grgrid.c + ${PROJECT_SOURCE_DIR}/c/gridsys.c + ${PROJECT_SOURCE_DIR}/c/lagrid.c + ${PROJECT_SOURCE_DIR}/c/niggli.c + ${PROJECT_SOURCE_DIR}/c/phonoc_utils.c + ${PROJECT_SOURCE_DIR}/c/snf3x3.c + ${PROJECT_SOURCE_DIR}/c/tetrahedron_method.c + ${PROJECT_SOURCE_DIR}/c/triplet.c + ${PROJECT_SOURCE_DIR}/c/triplet_grid.c + ${PROJECT_SOURCE_DIR}/c/triplet_iw.c) + + if(BUILD_SHARED_LIBS) + # Shared library + add_library(gridsys SHARED ${SOURCES_GRIDSYS}) + + if(OpenMP_FOUND) + target_link_libraries(gridsys PRIVATE OpenMP::OpenMP_C) + endif() + + target_include_directories(gridsys PRIVATE ${MY_INCLUDES}) + target_compile_definitions(gridsys PRIVATE THM_EPSILON=1e-10) + set_property(TARGET gridsys PROPERTY VERSION ${SERIAL}) + set_property(TARGET gridsys PROPERTY SOVERSION ${SOSERIAL}) + install(TARGETS gridsys LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) + else() + # Static link library + add_library(gridsys_static STATIC ${SOURCES_GRIDSYS}) + + if(OpenMP_FOUND) + target_link_libraries(gridsys_static PRIVATE OpenMP::OpenMP_C) + endif() + + target_include_directories(gridsys_static PRIVATE ${MY_INCLUDES}) + target_compile_definitions(gridsys_static PRIVATE THM_EPSILON=1e-10) + set_property(TARGET gridsys_static PROPERTY VERSION ${SERIAL}) + set_property(TARGET gridsys_static PROPERTY SOVERSION ${SOSERIAL}) + set_property(TARGET gridsys_static PROPERTY OUTPUT_NAME gridsys) + install(TARGETS gridsys_static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() + + # Header file + install(FILES ${PROJECT_SOURCE_DIR}/c/gridsys.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) endif() -if(WITH_Fortran) - add_subdirectory(fortran) +if(PHONO3PY_WITH_Fortran) + add_subdirectory(fortran) +endif() + +if(PHONO3PY_WITH_TESTS) + if(PHONO3PY_WITH_Fortran) + set(LIB_MOD_DIR ${CMAKE_CURRENT_BINARY_DIR}/fortran) + endif() + + add_subdirectory(ctest) endif() -if(WITH_TESTS) - if(WITH_Fortran) - set(LIB_MOD_DIR ${CMAKE_CURRENT_BINARY_DIR}/fortran) - endif() - add_subdirectory(ctest) +if(BUILD_NANOBIND_MODULE) + set_target_properties(phphcalc_lib PROPERTIES POSITION_INDEPENDENT_CODE ON) + set_target_properties(phononcalc_lib PROPERTIES POSITION_INDEPENDENT_CODE ON) + + execute_process( + COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE NB_DIR) + list(APPEND CMAKE_PREFIX_PATH "${NB_DIR}") + find_package(nanobind CONFIG REQUIRED) + nanobind_add_module(_phono3py STABLE_ABI ${PROJECT_SOURCE_DIR}/c/phono3py.h + ${PROJECT_SOURCE_DIR}/c/_phono3py.cpp) + nanobind_add_module(_phononcalc STABLE_ABI ${PROJECT_SOURCE_DIR}/c/phononcalc.h + ${PROJECT_SOURCE_DIR}/c/_phononcalc.cpp) + + target_link_libraries(_phono3py PRIVATE phphcalc_lib) + target_link_libraries(_phononcalc PRIVATE phononcalc_lib) + + target_compile_definitions(_phono3py PRIVATE THM_EPSILON=1e-10) + install(TARGETS _phono3py LIBRARY DESTINATION ${SKBUILD_PROJECT_NAME}) + install(TARGETS _phononcalc LIBRARY DESTINATION ${SKBUILD_PROJECT_NAME}) endif() diff --git a/c/_phono3py.cpp b/c/_phono3py.cpp new file mode 100644 index 00000000..5befc1cd --- /dev/null +++ b/c/_phono3py.cpp @@ -0,0 +1,1195 @@ +#include +#include +#include +#include + +#include "phono3py.h" +#include "phonoc_array.h" + +namespace nb = nanobind; + +static Larray *convert_to_larray(nb::ndarray<> npyary) { + long i; + Larray *ary; + + ary = (Larray *)malloc(sizeof(Larray)); + for (i = 0; i < npyary.ndim(); i++) { + ary->dims[i] = npyary.shape(i); + } + ary->data = (long *)npyary.data(); + return ary; +} + +static Darray *convert_to_darray(nb::ndarray<> npyary) { + int i; + Darray *ary; + + ary = (Darray *)malloc(sizeof(Darray)); + for (i = 0; i < npyary.ndim(); i++) { + ary->dims[i] = npyary.shape(i); + } + ary->data = (double *)npyary.data(); + return ary; +} + +// static void show_colmat_info(const PyArrayObject *py_collision_matrix, +// const long i_sigma, const long i_temp, +// const long adrs_shift) { +// long i; + +// printf(" Array_shape:("); +// for (i = 0; i < PyArray_NDIM(py_collision_matrix); i++) { +// printf("%d", (int)PyArray_DIM(py_collision_matrix, i)); +// if (i < PyArray_NDIM(py_collision_matrix) - 1) { +// printf(","); +// } else { +// printf("), "); +// } +// } +// printf("Data shift:%lu [%lu, %lu]\n", adrs_shift, i_sigma, i_temp); +// } + +void py_get_interaction(nb::ndarray<> py_fc3_normal_squared, + nb::ndarray<> py_g_zero, nb::ndarray<> py_frequencies, + nb::ndarray<> py_eigenvectors, + nb::ndarray<> py_triplets, + nb::ndarray<> py_bz_grid_addresses, + nb::ndarray<> py_D_diag, nb::ndarray<> py_Q, + nb::ndarray<> py_fc3, nb::ndarray<> py_svecs, + nb::ndarray<> py_multi, nb::ndarray<> py_masses, + nb::ndarray<> py_p2s_map, nb::ndarray<> py_s2p_map, + nb::ndarray<> py_band_indices, long symmetrize_fc3_q, + long make_r0_average, nb::ndarray<> py_all_shortest, + double cutoff_frequency, long openmp_per_triplets) { + Darray *fc3_normal_squared; + Darray *freqs; + _lapack_complex_double *eigvecs; + long(*triplets)[3]; + long num_triplets; + char *g_zero; + long(*bz_grid_addresses)[3]; + long *D_diag; + long(*Q)[3]; + double *fc3; + double(*svecs)[3]; + long(*multi)[2]; + double *masses; + char *all_shortest; + long *p2s; + long *s2p; + long *band_indices; + long multi_dims[2]; + long i; + long is_compact_fc3; + + fc3_normal_squared = convert_to_darray(py_fc3_normal_squared); + freqs = convert_to_darray(py_frequencies); + /* npy_cdouble and lapack_complex_double may not be compatible. */ + /* So eigenvectors should not be used in Python side */ + eigvecs = (_lapack_complex_double *)py_eigenvectors.data(); + triplets = (long(*)[3])py_triplets.data(); + num_triplets = (long)py_triplets.shape(0); + g_zero = (char *)py_g_zero.data(); + bz_grid_addresses = (long(*)[3])py_bz_grid_addresses.data(); + D_diag = (long *)py_D_diag.data(); + Q = (long(*)[3])py_Q.data(); + fc3 = (double *)py_fc3.data(); + if (py_fc3.shape(0) == py_fc3.shape(1)) { + is_compact_fc3 = 0; + } else { + is_compact_fc3 = 1; + } + svecs = (double(*)[3])py_svecs.data(); + for (i = 0; i < 2; i++) { + multi_dims[i] = py_multi.shape(i); + } + multi = (long(*)[2])py_multi.data(); + masses = (double *)py_masses.data(); + p2s = (long *)py_p2s_map.data(); + s2p = (long *)py_s2p_map.data(); + band_indices = (long *)py_band_indices.data(); + all_shortest = (char *)py_all_shortest.data(); + + ph3py_get_interaction(fc3_normal_squared, g_zero, freqs, eigvecs, triplets, + num_triplets, bz_grid_addresses, D_diag, Q, fc3, + is_compact_fc3, svecs, multi_dims, multi, masses, p2s, + s2p, band_indices, symmetrize_fc3_q, make_r0_average, + all_shortest, cutoff_frequency, openmp_per_triplets); + + free(fc3_normal_squared); + fc3_normal_squared = NULL; + free(freqs); + freqs = NULL; +} + +void py_get_pp_collision( + nb::ndarray<> py_gamma, nb::ndarray<> py_relative_grid_address, + nb::ndarray<> py_frequencies, nb::ndarray<> py_eigenvectors, + nb::ndarray<> py_triplets, nb::ndarray<> py_triplet_weights, + nb::ndarray<> py_bz_grid_addresses, nb::ndarray<> py_bz_map, + long bz_grid_type, nb::ndarray<> py_D_diag, nb::ndarray<> py_Q, + nb::ndarray<> py_fc3, nb::ndarray<> py_svecs, nb::ndarray<> py_multi, + nb::ndarray<> py_masses, nb::ndarray<> py_p2s_map, nb::ndarray<> py_s2p_map, + nb::ndarray<> py_band_indices, nb::ndarray<> py_temperatures, long is_NU, + long symmetrize_fc3_q, long make_r0_average, nb::ndarray<> py_all_shortest, + double cutoff_frequency, long openmp_per_triplets) { + double *gamma; + long(*relative_grid_address)[4][3]; + double *frequencies; + _lapack_complex_double *eigenvectors; + long(*triplets)[3]; + long num_triplets; + long *triplet_weights; + long(*bz_grid_addresses)[3]; + long *bz_map; + long *D_diag; + long(*Q)[3]; + double *fc3; + double(*svecs)[3]; + long(*multi)[2]; + double *masses; + long *p2s; + long *s2p; + Larray *band_indices; + Darray *temperatures; + char *all_shortest; + long multi_dims[2]; + long i; + long is_compact_fc3; + + gamma = (double *)py_gamma.data(); + relative_grid_address = (long(*)[4][3])py_relative_grid_address.data(); + frequencies = (double *)py_frequencies.data(); + eigenvectors = (_lapack_complex_double *)py_eigenvectors.data(); + triplets = (long(*)[3])py_triplets.data(); + num_triplets = (long)py_triplets.shape(0); + triplet_weights = (long *)py_triplet_weights.data(); + bz_grid_addresses = (long(*)[3])py_bz_grid_addresses.data(); + bz_map = (long *)py_bz_map.data(); + D_diag = (long *)py_D_diag.data(); + Q = (long(*)[3])py_Q.data(); + fc3 = (double *)py_fc3.data(); + if (py_fc3.shape(0) == py_fc3.shape(1)) { + is_compact_fc3 = 0; + } else { + is_compact_fc3 = 1; + } + svecs = (double(*)[3])py_svecs.data(); + for (i = 0; i < 2; i++) { + multi_dims[i] = py_multi.shape(i); + } + multi = (long(*)[2])py_multi.data(); + masses = (double *)py_masses.data(); + p2s = (long *)py_p2s_map.data(); + s2p = (long *)py_s2p_map.data(); + band_indices = convert_to_larray(py_band_indices); + temperatures = convert_to_darray(py_temperatures); + all_shortest = (char *)py_all_shortest.data(); + + ph3py_get_pp_collision( + gamma, relative_grid_address, frequencies, eigenvectors, triplets, + num_triplets, triplet_weights, bz_grid_addresses, bz_map, bz_grid_type, + D_diag, Q, fc3, is_compact_fc3, svecs, multi_dims, multi, masses, p2s, + s2p, band_indices, temperatures, is_NU, symmetrize_fc3_q, + make_r0_average, all_shortest, cutoff_frequency, openmp_per_triplets); + + free(band_indices); + band_indices = NULL; + free(temperatures); + temperatures = NULL; +} + +void py_get_pp_collision_with_sigma( + nb::ndarray<> py_gamma, double sigma, double sigma_cutoff, + nb::ndarray<> py_frequencies, nb::ndarray<> py_eigenvectors, + nb::ndarray<> py_triplets, nb::ndarray<> py_triplet_weights, + nb::ndarray<> py_bz_grid_addresses, nb::ndarray<> py_D_diag, + nb::ndarray<> py_Q, nb::ndarray<> py_fc3, nb::ndarray<> py_svecs, + nb::ndarray<> py_multi, nb::ndarray<> py_masses, nb::ndarray<> py_p2s_map, + nb::ndarray<> py_s2p_map, nb::ndarray<> py_band_indices, + nb::ndarray<> py_temperatures, long is_NU, long symmetrize_fc3_q, + long make_r0_average, nb::ndarray<> py_all_shortest, + double cutoff_frequency, long openmp_per_triplets) { + double *gamma; + double *frequencies; + _lapack_complex_double *eigenvectors; + long(*triplets)[3]; + long num_triplets; + long *triplet_weights; + long(*bz_grid_addresses)[3]; + long *D_diag; + long(*Q)[3]; + double *fc3; + double(*svecs)[3]; + long(*multi)[2]; + double *masses; + long *p2s; + long *s2p; + Larray *band_indices; + Darray *temperatures; + char *all_shortest; + long multi_dims[2]; + long i; + long is_compact_fc3; + + gamma = (double *)py_gamma.data(); + frequencies = (double *)py_frequencies.data(); + eigenvectors = (_lapack_complex_double *)py_eigenvectors.data(); + triplets = (long(*)[3])py_triplets.data(); + num_triplets = (long)py_triplets.shape(0); + triplet_weights = (long *)py_triplet_weights.data(); + bz_grid_addresses = (long(*)[3])py_bz_grid_addresses.data(); + D_diag = (long *)py_D_diag.data(); + Q = (long(*)[3])py_Q.data(); + fc3 = (double *)py_fc3.data(); + if (py_fc3.shape(0) == py_fc3.shape(1)) { + is_compact_fc3 = 0; + } else { + is_compact_fc3 = 1; + } + svecs = (double(*)[3])py_svecs.data(); + for (i = 0; i < 2; i++) { + multi_dims[i] = py_multi.shape(i); + } + multi = (long(*)[2])py_multi.data(); + masses = (double *)py_masses.data(); + p2s = (long *)py_p2s_map.data(); + s2p = (long *)py_s2p_map.data(); + band_indices = convert_to_larray(py_band_indices); + temperatures = convert_to_darray(py_temperatures); + all_shortest = (char *)py_all_shortest.data(); + + ph3py_get_pp_collision_with_sigma( + gamma, sigma, sigma_cutoff, frequencies, eigenvectors, triplets, + num_triplets, triplet_weights, bz_grid_addresses, D_diag, Q, fc3, + is_compact_fc3, svecs, multi_dims, multi, masses, p2s, s2p, + band_indices, temperatures, is_NU, symmetrize_fc3_q, make_r0_average, + all_shortest, cutoff_frequency, openmp_per_triplets); + + free(band_indices); + band_indices = NULL; + free(temperatures); + temperatures = NULL; +} + +void py_get_imag_self_energy_with_g( + nb::ndarray<> py_gamma, nb::ndarray<> py_fc3_normal_squared, + nb::ndarray<> py_triplets, nb::ndarray<> py_triplet_weights, + nb::ndarray<> py_frequencies, double temperature, nb::ndarray<> py_g, + nb::ndarray<> py_g_zero, double cutoff_frequency, + long frequency_point_index) { + Darray *fc3_normal_squared; + double *gamma; + double *g; + char *g_zero; + double *frequencies; + long(*triplets)[3]; + long *triplet_weights; + long num_frequency_points; + + fc3_normal_squared = convert_to_darray(py_fc3_normal_squared); + gamma = (double *)py_gamma.data(); + g = (double *)py_g.data(); + g_zero = (char *)py_g_zero.data(); + frequencies = (double *)py_frequencies.data(); + triplets = (long(*)[3])py_triplets.data(); + triplet_weights = (long *)py_triplet_weights.data(); + num_frequency_points = (long)py_g.shape(2); + + ph3py_get_imag_self_energy_at_bands_with_g( + gamma, fc3_normal_squared, frequencies, triplets, triplet_weights, g, + g_zero, temperature, cutoff_frequency, num_frequency_points, + frequency_point_index); + + free(fc3_normal_squared); + fc3_normal_squared = NULL; +} + +void py_get_detailed_imag_self_energy_with_g( + nb::ndarray<> py_gamma_detail, nb::ndarray<> py_gamma_N, + nb::ndarray<> py_gamma_U, nb::ndarray<> py_fc3_normal_squared, + nb::ndarray<> py_triplets, nb::ndarray<> py_triplet_weights, + nb::ndarray<> py_bz_grid_addresses, nb::ndarray<> py_frequencies, + double temperature, nb::ndarray<> py_g, nb::ndarray<> py_g_zero, + double cutoff_frequency) { + Darray *fc3_normal_squared; + double *gamma_detail; + double *gamma_N; + double *gamma_U; + double *g; + char *g_zero; + double *frequencies; + long(*triplets)[3]; + long *triplet_weights; + long(*bz_grid_addresses)[3]; + + fc3_normal_squared = convert_to_darray(py_fc3_normal_squared); + gamma_detail = (double *)py_gamma_detail.data(); + gamma_N = (double *)py_gamma_N.data(); + gamma_U = (double *)py_gamma_U.data(); + g = (double *)py_g.data(); + g_zero = (char *)py_g_zero.data(); + frequencies = (double *)py_frequencies.data(); + triplets = (long(*)[3])py_triplets.data(); + triplet_weights = (long *)py_triplet_weights.data(); + bz_grid_addresses = (long(*)[3])py_bz_grid_addresses.data(); + + ph3py_get_detailed_imag_self_energy_at_bands_with_g( + gamma_detail, gamma_N, gamma_U, fc3_normal_squared, frequencies, + triplets, triplet_weights, bz_grid_addresses, g, g_zero, temperature, + cutoff_frequency); + + free(fc3_normal_squared); + fc3_normal_squared = NULL; +} + +void py_get_real_self_energy_at_bands( + nb::ndarray<> py_shift, nb::ndarray<> py_fc3_normal_squared, + nb::ndarray<> py_triplets, nb::ndarray<> py_triplet_weights, + nb::ndarray<> py_frequencies, nb::ndarray<> py_band_indices, + double temperature, double epsilon, double unit_conversion_factor, + double cutoff_frequency) { + Darray *fc3_normal_squared; + double *shift; + double *frequencies; + long *band_indices; + long(*triplets)[3]; + long *triplet_weights; + + fc3_normal_squared = convert_to_darray(py_fc3_normal_squared); + shift = (double *)py_shift.data(); + frequencies = (double *)py_frequencies.data(); + band_indices = (long *)py_band_indices.data(); + triplets = (long(*)[3])py_triplets.data(); + triplet_weights = (long *)py_triplet_weights.data(); + + ph3py_get_real_self_energy_at_bands( + shift, fc3_normal_squared, band_indices, frequencies, triplets, + triplet_weights, epsilon, temperature, unit_conversion_factor, + cutoff_frequency); + + free(fc3_normal_squared); + fc3_normal_squared = NULL; +} + +void py_get_real_self_energy_at_frequency_point( + nb::ndarray<> py_shift, double frequency_point, + nb::ndarray<> py_fc3_normal_squared, nb::ndarray<> py_triplets, + nb::ndarray<> py_triplet_weights, nb::ndarray<> py_frequencies, + nb::ndarray<> py_band_indices, double temperature, double epsilon, + double unit_conversion_factor, double cutoff_frequency) { + Darray *fc3_normal_squared; + double *shift; + double *frequencies; + long *band_indices; + long(*triplets)[3]; + long *triplet_weights; + + fc3_normal_squared = convert_to_darray(py_fc3_normal_squared); + shift = (double *)py_shift.data(); + frequencies = (double *)py_frequencies.data(); + band_indices = (long *)py_band_indices.data(); + triplets = (long(*)[3])py_triplets.data(); + triplet_weights = (long *)py_triplet_weights.data(); + + ph3py_get_real_self_energy_at_frequency_point( + shift, frequency_point, fc3_normal_squared, band_indices, frequencies, + triplets, triplet_weights, epsilon, temperature, unit_conversion_factor, + cutoff_frequency); + + free(fc3_normal_squared); + fc3_normal_squared = NULL; +} + +void py_get_collision_matrix( + nb::ndarray<> py_collision_matrix, nb::ndarray<> py_fc3_normal_squared, + nb::ndarray<> py_frequencies, nb::ndarray<> py_g, nb::ndarray<> py_triplets, + nb::ndarray<> py_triplets_map, nb::ndarray<> py_map_q, + nb::ndarray<> py_rotated_grid_points, nb::ndarray<> py_rotations_cartesian, + double temperature, double unit_conversion_factor, + double cutoff_frequency) { + Darray *fc3_normal_squared; + double *collision_matrix; + double *g; + double *frequencies; + long(*triplets)[3]; + long *triplets_map; + long *map_q; + long *rotated_grid_points; + long num_gp, num_ir_gp, num_rot; + double *rotations_cartesian; + + fc3_normal_squared = convert_to_darray(py_fc3_normal_squared); + collision_matrix = (double *)py_collision_matrix.data(); + g = (double *)py_g.data(); + frequencies = (double *)py_frequencies.data(); + triplets = (long(*)[3])py_triplets.data(); + triplets_map = (long *)py_triplets_map.data(); + num_gp = (long)py_triplets_map.shape(0); + map_q = (long *)py_map_q.data(); + rotated_grid_points = (long *)py_rotated_grid_points.data(); + num_ir_gp = (long)py_rotated_grid_points.shape(0); + num_rot = (long)py_rotated_grid_points.shape(1); + rotations_cartesian = (double *)py_rotations_cartesian.data(); + + assert(num_rot == py_rotations_cartesian.shape(0)); + assert(num_gp == py_frequencies.shape(0)); + + ph3py_get_collision_matrix(collision_matrix, fc3_normal_squared, + frequencies, triplets, triplets_map, map_q, + rotated_grid_points, rotations_cartesian, g, + num_ir_gp, num_gp, num_rot, temperature, + unit_conversion_factor, cutoff_frequency); + + free(fc3_normal_squared); + fc3_normal_squared = NULL; +} + +void py_get_reducible_collision_matrix( + nb::ndarray<> py_collision_matrix, nb::ndarray<> py_fc3_normal_squared, + nb::ndarray<> py_frequencies, nb::ndarray<> py_g, nb::ndarray<> py_triplets, + nb::ndarray<> py_triplets_map, nb::ndarray<> py_map_q, double temperature, + double unit_conversion_factor, double cutoff_frequency) { + Darray *fc3_normal_squared; + double *collision_matrix; + double *g; + double *frequencies; + long(*triplets)[3]; + long *triplets_map; + long num_gp; + long *map_q; + + fc3_normal_squared = convert_to_darray(py_fc3_normal_squared); + collision_matrix = (double *)py_collision_matrix.data(); + g = (double *)py_g.data(); + frequencies = (double *)py_frequencies.data(); + triplets = (long(*)[3])py_triplets.data(); + triplets_map = (long *)py_triplets_map.data(); + num_gp = (long)py_triplets_map.shape(0); + map_q = (long *)py_map_q.data(); + + ph3py_get_reducible_collision_matrix( + collision_matrix, fc3_normal_squared, frequencies, triplets, + triplets_map, map_q, g, num_gp, temperature, unit_conversion_factor, + cutoff_frequency); + + free(fc3_normal_squared); + fc3_normal_squared = NULL; +} + +void py_symmetrize_collision_matrix(nb::ndarray<> py_collision_matrix) { + double *collision_matrix; + long num_band, num_grid_points, num_temp, num_sigma; + long num_column; + + collision_matrix = (double *)py_collision_matrix.data(); + num_sigma = (long)py_collision_matrix.shape(0); + num_temp = (long)py_collision_matrix.shape(1); + num_grid_points = (long)py_collision_matrix.shape(2); + num_band = (long)py_collision_matrix.shape(3); + + if (py_collision_matrix.ndim() == 8) { + num_column = num_grid_points * num_band * 3; + } else { + num_column = num_grid_points * num_band; + } + + ph3py_symmetrize_collision_matrix(collision_matrix, num_column, num_temp, + num_sigma); +} + +void py_expand_collision_matrix(nb::ndarray<> py_collision_matrix, + nb::ndarray<> py_ir_grid_points, + nb::ndarray<> py_rot_grid_points) { + double *collision_matrix; + long *rot_grid_points; + long *ir_grid_points; + long num_band, num_grid_points, num_temp, num_sigma, num_rot, num_ir_gp; + + collision_matrix = (double *)py_collision_matrix.data(); + rot_grid_points = (long *)py_rot_grid_points.data(); + ir_grid_points = (long *)py_ir_grid_points.data(); + num_sigma = (long)py_collision_matrix.shape(0); + num_temp = (long)py_collision_matrix.shape(1); + num_grid_points = (long)py_collision_matrix.shape(2); + num_band = (long)py_collision_matrix.shape(3); + num_rot = (long)py_rot_grid_points.shape(0); + num_ir_gp = (long)py_ir_grid_points.shape(0); + + ph3py_expand_collision_matrix(collision_matrix, rot_grid_points, + ir_grid_points, num_ir_gp, num_grid_points, + num_rot, num_sigma, num_temp, num_band); +} + +void py_distribute_fc3(nb::ndarray<> force_constants_third, long target, + long source, nb::ndarray<> atom_mapping_py, + nb::ndarray<> rotation_cart_inv) { + double *fc3; + double *rot_cart_inv; + long *atom_mapping; + long num_atom; + + fc3 = (double *)force_constants_third.data(); + rot_cart_inv = (double *)rotation_cart_inv.data(); + atom_mapping = (long *)atom_mapping_py.data(); + num_atom = (long)atom_mapping_py.shape(0); + + ph3py_distribute_fc3(fc3, target, source, atom_mapping, num_atom, + rot_cart_inv); +} + +void py_rotate_delta_fc2s(nb::ndarray<> py_fc3, nb::ndarray<> py_delta_fc2s, + nb::ndarray<> py_inv_U, + nb::ndarray<> py_site_sym_cart, + nb::ndarray<> py_rot_map_syms) { + double(*fc3)[3][3][3]; + double(*delta_fc2s)[3][3]; + double *inv_U; + double(*site_sym_cart)[3][3]; + long *rot_map_syms; + long num_atom, num_disp, num_site_sym; + + /* (num_atom, num_atom, 3, 3, 3) */ + fc3 = (double(*)[3][3][3])py_fc3.data(); + /* (n_u1, num_atom, num_atom, 3, 3) */ + delta_fc2s = (double(*)[3][3])py_delta_fc2s.data(); + /* (3, n_u1 * n_sym) */ + inv_U = (double *)py_inv_U.data(); + /* (n_sym, 3, 3) */ + site_sym_cart = (double(*)[3][3])py_site_sym_cart.data(); + /* (n_sym, natom) */ + rot_map_syms = (long *)py_rot_map_syms.data(); + + num_atom = (long)py_fc3.shape(0); + num_disp = (long)py_delta_fc2s.shape(0); + num_site_sym = (long)py_site_sym_cart.shape(0); + + ph3py_rotate_delta_fc2(fc3, delta_fc2s, inv_U, site_sym_cart, rot_map_syms, + num_atom, num_site_sym, num_disp); +} + +void py_get_isotope_strength( + nb::ndarray<> py_gamma, long grid_point, nb::ndarray<> py_ir_grid_points, + nb::ndarray<> py_weights, nb::ndarray<> py_mass_variances, + nb::ndarray<> py_frequencies, nb::ndarray<> py_eigenvectors, + nb::ndarray<> py_band_indices, double sigma, double cutoff_frequency) { + double *gamma; + double *frequencies; + long *ir_grid_points; + double *weights; + _lapack_complex_double *eigenvectors; + long *band_indices; + double *mass_variances; + long num_band, num_band0, num_ir_grid_points; + + gamma = (double *)py_gamma.data(); + frequencies = (double *)py_frequencies.data(); + eigenvectors = (_lapack_complex_double *)py_eigenvectors.data(); + ir_grid_points = (long *)py_ir_grid_points.data(); + weights = (double *)py_weights.data(); + band_indices = (long *)py_band_indices.data(); + mass_variances = (double *)py_mass_variances.data(); + num_band = (long)py_frequencies.shape(1); + num_band0 = (long)py_band_indices.shape(0); + num_ir_grid_points = (long)py_ir_grid_points.shape(0); + + ph3py_get_isotope_scattering_strength( + gamma, grid_point, ir_grid_points, weights, mass_variances, frequencies, + eigenvectors, num_ir_grid_points, band_indices, num_band, num_band0, + sigma, cutoff_frequency); +} + +void py_get_thm_isotope_strength( + nb::ndarray<> py_gamma, long grid_point, nb::ndarray<> py_ir_grid_points, + nb::ndarray<> py_weights, nb::ndarray<> py_mass_variances, + nb::ndarray<> py_frequencies, nb::ndarray<> py_eigenvectors, + nb::ndarray<> py_band_indices, nb::ndarray<> py_integration_weights, + double cutoff_frequency) { + double *gamma; + double *frequencies; + long *ir_grid_points; + double *weights; + _lapack_complex_double *eigenvectors; + long *band_indices; + double *mass_variances; + long num_band, num_band0, num_ir_grid_points; + double *integration_weights; + + gamma = (double *)py_gamma.data(); + frequencies = (double *)py_frequencies.data(); + ir_grid_points = (long *)py_ir_grid_points.data(); + weights = (double *)py_weights.data(); + eigenvectors = (_lapack_complex_double *)py_eigenvectors.data(); + band_indices = (long *)py_band_indices.data(); + mass_variances = (double *)py_mass_variances.data(); + num_band = (long)py_frequencies.shape(1); + num_band0 = (long)py_band_indices.shape(0); + integration_weights = (double *)py_integration_weights.data(); + num_ir_grid_points = (long)py_ir_grid_points.shape(0); + + ph3py_get_thm_isotope_scattering_strength( + gamma, grid_point, ir_grid_points, weights, mass_variances, frequencies, + eigenvectors, num_ir_grid_points, band_indices, num_band, num_band0, + integration_weights, cutoff_frequency); +} + +void py_get_permutation_symmetry_fc3(nb::ndarray<> py_fc3) { + double *fc3; + long num_atom; + + fc3 = (double *)py_fc3.data(); + num_atom = (long)py_fc3.shape(0); + + ph3py_get_permutation_symmetry_fc3(fc3, num_atom); +} + +void py_get_permutation_symmetry_compact_fc3(nb::ndarray<> py_fc3, + nb::ndarray<> py_permutations, + nb::ndarray<> py_s2pp_map, + nb::ndarray<> py_p2s_map, + nb::ndarray<> py_nsym_list) { + double *fc3; + long *s2pp; + long *p2s; + long *nsym_list; + long *perms; + long n_patom, n_satom; + + fc3 = (double *)py_fc3.data(); + perms = (long *)py_permutations.data(); + s2pp = (long *)py_s2pp_map.data(); + p2s = (long *)py_p2s_map.data(); + nsym_list = (long *)py_nsym_list.data(); + n_patom = (long)py_fc3.shape(0); + n_satom = (long)py_fc3.shape(1); + + ph3py_get_permutation_symmetry_compact_fc3(fc3, p2s, s2pp, nsym_list, perms, + n_satom, n_patom); +} + +void py_transpose_compact_fc3(nb::ndarray<> py_fc3, + nb::ndarray<> py_permutations, + nb::ndarray<> py_s2pp_map, + nb::ndarray<> py_p2s_map, + nb::ndarray<> py_nsym_list, long t_type) { + double *fc3; + long *s2pp; + long *p2s; + long *nsym_list; + long *perms; + long n_patom, n_satom; + + fc3 = (double *)py_fc3.data(); + perms = (long *)py_permutations.data(); + s2pp = (long *)py_s2pp_map.data(); + p2s = (long *)py_p2s_map.data(); + nsym_list = (long *)py_nsym_list.data(); + n_patom = (long)py_fc3.shape(0); + n_satom = (long)py_fc3.shape(1); + + ph3py_transpose_compact_fc3(fc3, p2s, s2pp, nsym_list, perms, n_satom, + n_patom, t_type); +} + +void py_get_thm_relative_grid_address(nb::ndarray<> py_relative_grid_address, + nb::ndarray<> py_reciprocal_lattice_py) { + long(*relative_grid_address)[4][3]; + double(*reciprocal_lattice)[3]; + + relative_grid_address = (long(*)[4][3])py_relative_grid_address.data(); + reciprocal_lattice = (double(*)[3])py_reciprocal_lattice_py.data(); + + ph3py_get_relative_grid_address(relative_grid_address, reciprocal_lattice); +} + +void py_get_neighboring_grid_points(nb::ndarray<> py_relative_grid_points, + nb::ndarray<> py_grid_points, + nb::ndarray<> py_relative_grid_address, + nb::ndarray<> py_D_diag, + nb::ndarray<> py_bz_grid_address, + nb::ndarray<> py_bz_map, + long bz_grid_type) { + long *relative_grid_points; + long *grid_points; + long num_grid_points, num_relative_grid_address; + long(*relative_grid_address)[3]; + long *D_diag; + long(*bz_grid_address)[3]; + long *bz_map; + + relative_grid_points = (long *)py_relative_grid_points.data(); + grid_points = (long *)py_grid_points.data(); + num_grid_points = (long)py_grid_points.shape(0); + relative_grid_address = (long(*)[3])py_relative_grid_address.data(); + num_relative_grid_address = (long)py_relative_grid_address.shape(0); + D_diag = (long *)py_D_diag.data(); + bz_grid_address = (long(*)[3])py_bz_grid_address.data(); + bz_map = (long *)py_bz_map.data(); + + ph3py_get_neighboring_gird_points( + relative_grid_points, grid_points, relative_grid_address, D_diag, + bz_grid_address, bz_map, bz_grid_type, num_grid_points, + num_relative_grid_address); +} + +void py_get_thm_integration_weights_at_grid_points( + nb::ndarray<> py_iw, nb::ndarray<> py_frequency_points, + nb::ndarray<> py_relative_grid_address, nb::ndarray<> py_D_diag, + nb::ndarray<> py_grid_points, nb::ndarray<> py_frequencies, + nb::ndarray<> py_bz_grid_address, nb::ndarray<> py_bz_map, + nb::ndarray<> py_gp2irgp_map, long bz_grid_type, const char *function) { + double *iw; + double *frequency_points; + long num_frequency_points, num_band, num_gp; + long(*relative_grid_address)[4][3]; + long *D_diag; + long *grid_points; + long(*bz_grid_address)[3]; + long *bz_map; + long *gp2irgp_map; + double *frequencies; + + iw = (double *)py_iw.data(); + frequency_points = (double *)py_frequency_points.data(); + num_frequency_points = (long)py_frequency_points.shape(0); + relative_grid_address = (long(*)[4][3])py_relative_grid_address.data(); + D_diag = (long *)py_D_diag.data(); + grid_points = (long *)py_grid_points.data(); + num_gp = (long)py_grid_points.shape(0); + bz_grid_address = (long(*)[3])py_bz_grid_address.data(); + bz_map = (long *)py_bz_map.data(); + gp2irgp_map = (long *)py_gp2irgp_map.data(); + frequencies = (double *)py_frequencies.data(); + num_band = (long)py_frequencies.shape(1); + + ph3py_get_thm_integration_weights_at_grid_points( + iw, frequency_points, num_frequency_points, num_band, num_gp, + relative_grid_address, D_diag, grid_points, bz_grid_address, bz_map, + bz_grid_type, frequencies, gp2irgp_map, function[0]); +} + +long py_tpl_get_triplets_reciprocal_mesh_at_q( + nb::ndarray<> py_map_triplets, nb::ndarray<> py_map_q, + long fixed_grid_number, nb::ndarray<> py_D_diag, long is_time_reversal, + nb::ndarray<> py_rotations, long swappable) { + long *map_triplets; + long *map_q; + long *D_diag; + long(*rot)[3][3]; + long num_rot; + long num_ir; + + map_triplets = (long *)py_map_triplets.data(); + map_q = (long *)py_map_q.data(); + D_diag = (long *)py_D_diag.data(); + rot = (long(*)[3][3])py_rotations.data(); + num_rot = (long)py_rotations.shape(0); + + num_ir = ph3py_get_triplets_reciprocal_mesh_at_q( + map_triplets, map_q, fixed_grid_number, D_diag, is_time_reversal, + num_rot, rot, swappable); + + return num_ir; +} + +long py_tpl_get_BZ_triplets_at_q(nb::ndarray<> py_triplets, long grid_point, + nb::ndarray<> py_bz_grid_address, + nb::ndarray<> py_bz_map, + nb::ndarray<> py_map_triplets, + nb::ndarray<> py_D_diag, nb::ndarray<> py_Q, + long bz_grid_type) { + long(*triplets)[3]; + long(*bz_grid_address)[3]; + long *bz_map; + long *map_triplets; + long num_map_triplets; + long *D_diag; + long(*Q)[3]; + long num_ir; + + triplets = (long(*)[3])py_triplets.data(); + bz_grid_address = (long(*)[3])py_bz_grid_address.data(); + bz_map = (long *)py_bz_map.data(); + map_triplets = (long *)py_map_triplets.data(); + num_map_triplets = (long)py_map_triplets.shape(0); + D_diag = (long *)py_D_diag.data(); + Q = (long(*)[3])py_Q.data(); + + num_ir = ph3py_get_BZ_triplets_at_q(triplets, grid_point, bz_grid_address, + bz_map, map_triplets, num_map_triplets, + D_diag, Q, bz_grid_type); + + return num_ir; +} + +void py_get_triplets_integration_weights( + nb::ndarray<> py_iw, nb::ndarray<> py_iw_zero, + nb::ndarray<> py_frequency_points, nb::ndarray<> py_relative_grid_address, + nb::ndarray<> py_D_diag, nb::ndarray<> py_triplets, + nb::ndarray<> py_frequencies1, nb::ndarray<> py_frequencies2, + nb::ndarray<> py_bz_grid_addresses, nb::ndarray<> py_bz_map, + long bz_grid_type, long tp_type) { + double *iw; + char *iw_zero; + double *frequency_points; + long(*relative_grid_address)[4][3]; + long *D_diag; + long(*triplets)[3]; + long(*bz_grid_addresses)[3]; + long *bz_map; + double *frequencies1, *frequencies2; + long num_band0, num_band1, num_band2, num_triplets; + + iw = (double *)py_iw.data(); + iw_zero = (char *)py_iw_zero.data(); + frequency_points = (double *)py_frequency_points.data(); + num_band0 = (long)py_frequency_points.shape(0); + relative_grid_address = (long(*)[4][3])py_relative_grid_address.data(); + D_diag = (long *)py_D_diag.data(); + triplets = (long(*)[3])py_triplets.data(); + num_triplets = (long)py_triplets.shape(0); + bz_grid_addresses = (long(*)[3])py_bz_grid_addresses.data(); + bz_map = (long *)py_bz_map.data(); + frequencies1 = (double *)py_frequencies1.data(); + frequencies2 = (double *)py_frequencies2.data(); + num_band1 = (long)py_frequencies1.shape(1); + num_band2 = (long)py_frequencies2.shape(1); + + ph3py_get_integration_weight( + iw, iw_zero, frequency_points, num_band0, relative_grid_address, D_diag, + triplets, num_triplets, bz_grid_addresses, bz_map, bz_grid_type, + frequencies1, num_band1, frequencies2, num_band2, tp_type, 1); +} + +void py_get_triplets_integration_weights_with_sigma( + nb::ndarray<> py_iw, nb::ndarray<> py_iw_zero, + nb::ndarray<> py_frequency_points, nb::ndarray<> py_triplets, + nb::ndarray<> py_frequencies, double sigma, double sigma_cutoff) { + double *iw; + char *iw_zero; + double *frequency_points; + long(*triplets)[3]; + double *frequencies; + long num_band0, num_band, num_iw, num_triplets; + + iw = (double *)py_iw.data(); + iw_zero = (char *)py_iw_zero.data(); + frequency_points = (double *)py_frequency_points.data(); + num_band0 = (long)py_frequency_points.shape(0); + triplets = (long(*)[3])py_triplets.data(); + num_triplets = (long)py_triplets.shape(0); + frequencies = (double *)py_frequencies.data(); + num_band = (long)py_frequencies.shape(1); + num_iw = (long)py_iw.shape(0); + + ph3py_get_integration_weight_with_sigma( + iw, iw_zero, sigma, sigma_cutoff, frequency_points, num_band0, triplets, + num_triplets, frequencies, num_band, num_iw); +} + +long py_get_grid_index_from_address(nb::ndarray<> py_address, + nb::ndarray<> py_D_diag) { + long *address; + long *D_diag; + long gp; + + address = (long *)py_address.data(); + D_diag = (long *)py_D_diag.data(); + + gp = ph3py_get_grid_index_from_address(address, D_diag); + + return gp; +} + +long py_get_ir_grid_map(nb::ndarray<> py_grid_mapping_table, + nb::ndarray<> py_D_diag, nb::ndarray<> py_is_shift, + nb::ndarray<> py_rotations) { + long *D_diag; + long *is_shift; + long(*rot)[3][3]; + long num_rot; + + long *grid_mapping_table; + long num_ir; + + D_diag = (long *)py_D_diag.data(); + is_shift = (long *)py_is_shift.data(); + rot = (long(*)[3][3])py_rotations.data(); + num_rot = (long)py_rotations.shape(0); + grid_mapping_table = (long *)py_grid_mapping_table.data(); + + num_ir = ph3py_get_ir_grid_map(grid_mapping_table, D_diag, is_shift, rot, + num_rot); + return num_ir; +} + +void py_get_gr_grid_addresses(nb::ndarray<> py_gr_grid_addresses, + nb::ndarray<> py_D_diag) { + long(*gr_grid_addresses)[3]; + long *D_diag; + + gr_grid_addresses = (long(*)[3])py_gr_grid_addresses.data(); + D_diag = (long *)py_D_diag.data(); + + ph3py_get_gr_grid_addresses(gr_grid_addresses, D_diag); +} + +long py_get_reciprocal_rotations(nb::ndarray<> py_rec_rotations, + nb::ndarray<> py_rotations, + long is_time_reversal) { + long(*rec_rotations)[3][3]; + long(*rotations)[3][3]; + long num_rot, num_rec_rot; + + rec_rotations = (long(*)[3][3])py_rec_rotations.data(); + rotations = (long(*)[3][3])py_rotations.data(); + num_rot = (long)py_rotations.shape(0); + + num_rec_rot = ph3py_get_reciprocal_rotations(rec_rotations, rotations, + num_rot, is_time_reversal); + + return num_rec_rot; +} + +bool py_transform_rotations(nb::ndarray<> py_transformed_rotations, + nb::ndarray<> py_rotations, nb::ndarray<> py_D_diag, + nb::ndarray<> py_Q) { + long(*transformed_rotations)[3][3]; + long(*rotations)[3][3]; + long *D_diag; + long(*Q)[3]; + long num_rot, succeeded; + + transformed_rotations = (long(*)[3][3])py_transformed_rotations.data(); + rotations = (long(*)[3][3])py_rotations.data(); + D_diag = (long *)py_D_diag.data(); + Q = (long(*)[3])py_Q.data(); + num_rot = (long)py_transformed_rotations.shape(0); + + succeeded = ph3py_transform_rotations(transformed_rotations, rotations, + num_rot, D_diag, Q); + if (succeeded) { + return true; + } else { + return false; + } +} + +bool py_get_snf3x3(nb::ndarray<> py_D_diag, nb::ndarray<> py_P, + nb::ndarray<> py_Q, nb::ndarray<> py_A) { + long *D_diag; + long(*P)[3]; + long(*Q)[3]; + long(*A)[3]; + long succeeded; + + D_diag = (long *)py_D_diag.data(); + P = (long(*)[3])py_P.data(); + Q = (long(*)[3])py_Q.data(); + A = (long(*)[3])py_A.data(); + + succeeded = ph3py_get_snf3x3(D_diag, P, Q, A); + if (succeeded) { + return true; + } else { + return false; + } +} + +long py_get_bz_grid_addresses(nb::ndarray<> py_bz_grid_addresses, + nb::ndarray<> py_bz_map, nb::ndarray<> py_bzg2grg, + nb::ndarray<> py_D_diag, nb::ndarray<> py_Q, + nb::ndarray<> py_PS, + nb::ndarray<> py_reciprocal_lattice, long type) { + long(*bz_grid_addresses)[3]; + long *bz_map; + long *bzg2grg; + long *D_diag; + long(*Q)[3]; + long *PS; + double(*reciprocal_lattice)[3]; + long num_total_gp; + + bz_grid_addresses = (long(*)[3])py_bz_grid_addresses.data(); + bz_map = (long *)py_bz_map.data(); + bzg2grg = (long *)py_bzg2grg.data(); + D_diag = (long *)py_D_diag.data(); + Q = (long(*)[3])py_Q.data(); + PS = (long *)py_PS.data(); + reciprocal_lattice = (double(*)[3])py_reciprocal_lattice.data(); + + num_total_gp = + ph3py_get_bz_grid_addresses(bz_grid_addresses, bz_map, bzg2grg, D_diag, + Q, PS, reciprocal_lattice, type); + + return num_total_gp; +} + +long py_rotate_bz_grid_addresses(long bz_grid_index, nb::ndarray<> py_rotation, + nb::ndarray<> py_bz_grid_addresses, + nb::ndarray<> py_bz_map, + nb::ndarray<> py_D_diag, nb::ndarray<> py_PS, + long type) { + long(*bz_grid_addresses)[3]; + long(*rotation)[3]; + long *bz_map; + long *D_diag; + long *PS; + long ret_bz_gp; + + bz_grid_addresses = (long(*)[3])py_bz_grid_addresses.data(); + rotation = (long(*)[3])py_rotation.data(); + bz_map = (long *)py_bz_map.data(); + D_diag = (long *)py_D_diag.data(); + PS = (long *)py_PS.data(); + + ret_bz_gp = ph3py_rotate_bz_grid_index( + bz_grid_index, rotation, bz_grid_addresses, bz_map, D_diag, PS, type); + + return ret_bz_gp; +} + +long py_diagonalize_collision_matrix(nb::ndarray<> py_collision_matrix, + nb::ndarray<> py_eigenvalues, long i_sigma, + long i_temp, double cutoff, long solver, + long is_pinv) { + double *collision_matrix; + double *eigvals; + long num_temp, num_grid_point, num_band; + long num_column, adrs_shift; + long info; + + collision_matrix = (double *)py_collision_matrix.data(); + eigvals = (double *)py_eigenvalues.data(); + + if (py_collision_matrix.ndim() == 2) { + num_temp = 1; + num_column = py_collision_matrix.shape(1); + } else { + num_temp = py_collision_matrix.shape(1); + num_grid_point = py_collision_matrix.shape(2); + num_band = py_collision_matrix.shape(3); + if (py_collision_matrix.ndim() == 8) { + num_column = num_grid_point * num_band * 3; + } else { + num_column = num_grid_point * num_band; + } + } + adrs_shift = (i_sigma * num_column * num_column * num_temp + + i_temp * num_column * num_column); + + /* show_colmat_info(py_collision_matrix, i_sigma, i_temp, adrs_shift); */ + + info = ph3py_phonopy_dsyev(collision_matrix + adrs_shift, eigvals, + num_column, solver); + if (is_pinv) { + ph3py_pinv_from_eigensolution(collision_matrix + adrs_shift, eigvals, + num_column, cutoff, 0); + } + + return info; +} + +void py_pinv_from_eigensolution(nb::ndarray<> py_collision_matrix, + nb::ndarray<> py_eigenvalues, long i_sigma, + long i_temp, double cutoff, long pinv_method) { + double *collision_matrix; + double *eigvals; + long num_temp, num_grid_point, num_band; + long num_column, adrs_shift; + + collision_matrix = (double *)py_collision_matrix.data(); + eigvals = (double *)py_eigenvalues.data(); + num_temp = py_collision_matrix.shape(1); + num_grid_point = py_collision_matrix.shape(2); + num_band = py_collision_matrix.shape(3); + + if (py_collision_matrix.ndim() == 8) { + num_column = num_grid_point * num_band * 3; + } else { + num_column = num_grid_point * num_band; + } + adrs_shift = (i_sigma * num_column * num_column * num_temp + + i_temp * num_column * num_column); + + /* show_colmat_info(py_collision_matrix, i_sigma, i_temp, adrs_shift); */ + + ph3py_pinv_from_eigensolution(collision_matrix + adrs_shift, eigvals, + num_column, cutoff, pinv_method); +} + +long py_get_default_colmat_solver() { +#if defined(MKL_LAPACKE) || defined(SCIPY_MKL_H) + return (long)1; +#else + return (long)4; +#endif +} + +long py_lapacke_pinv(nb::ndarray<> data_out_py, nb::ndarray<> data_in_py, + double cutoff) { + long m; + long n; + double *data_in; + double *data_out; + long info; + + m = data_in_py.shape(0); + n = data_in_py.shape(1); + data_in = (double *)data_in_py.data(); + data_out = (double *)data_out_py.data(); + + info = ph3py_phonopy_pinv(data_out, data_in, m, n, cutoff); + + return info; +} + +long py_get_omp_max_threads() { return ph3py_get_max_threads(); } + +NB_MODULE(_phono3py, m) { + m.def("interaction", &py_get_interaction); + m.def("pp_collision", &py_get_pp_collision); + m.def("pp_collision_with_sigma", &py_get_pp_collision_with_sigma); + m.def("imag_self_energy_with_g", &py_get_imag_self_energy_with_g); + m.def("detailed_imag_self_energy_with_g", + &py_get_detailed_imag_self_energy_with_g); + m.def("real_self_energy_at_bands", &py_get_real_self_energy_at_bands); + m.def("real_self_energy_at_frequency_point", + &py_get_real_self_energy_at_frequency_point); + m.def("collision_matrix", &py_get_collision_matrix); + m.def("reducible_collision_matrix", &py_get_reducible_collision_matrix); + m.def("symmetrize_collision_matrix", &py_symmetrize_collision_matrix); + m.def("expand_collision_matrix", &py_expand_collision_matrix); + m.def("distribute_fc3", &py_distribute_fc3); + m.def("rotate_delta_fc2s", &py_rotate_delta_fc2s); + m.def("isotope_strength", &py_get_isotope_strength); + m.def("thm_isotope_strength", &py_get_thm_isotope_strength); + m.def("permutation_symmetry_fc3", &py_get_permutation_symmetry_fc3); + m.def("permutation_symmetry_compact_fc3", + &py_get_permutation_symmetry_compact_fc3); + m.def("transpose_compact_fc3", &py_transpose_compact_fc3); + m.def("tetrahedra_relative_grid_address", + &py_get_thm_relative_grid_address); + m.def("neighboring_grid_points", &py_get_neighboring_grid_points); + m.def("integration_weights_at_grid_points", + &py_get_thm_integration_weights_at_grid_points); + m.def("triplets_reciprocal_mesh_at_q", + &py_tpl_get_triplets_reciprocal_mesh_at_q); + m.def("BZ_triplets_at_q", &py_tpl_get_BZ_triplets_at_q); + m.def("triplets_integration_weights", &py_get_triplets_integration_weights); + m.def("triplets_integration_weights_with_sigma", + &py_get_triplets_integration_weights_with_sigma); + m.def("grid_index_from_address", &py_get_grid_index_from_address); + m.def("ir_grid_map", &py_get_ir_grid_map); + m.def("gr_grid_addresses", &py_get_gr_grid_addresses); + m.def("reciprocal_rotations", &py_get_reciprocal_rotations); + m.def("transform_rotations", &py_transform_rotations); + m.def("snf3x3", &py_get_snf3x3); + m.def("bz_grid_addresses", &py_get_bz_grid_addresses); + m.def("rotate_bz_grid_index", &py_rotate_bz_grid_addresses); + m.def("diagonalize_collision_matrix", &py_diagonalize_collision_matrix); + m.def("pinv_from_eigensolution", &py_pinv_from_eigensolution); + m.def("default_colmat_solver", &py_get_default_colmat_solver); + m.def("lapacke_pinv", &py_lapacke_pinv); + m.def("omp_max_threads", &py_get_omp_max_threads); +} diff --git a/c/_phononcalc.cpp b/c/_phononcalc.cpp new file mode 100644 index 00000000..6c21b816 --- /dev/null +++ b/c/_phononcalc.cpp @@ -0,0 +1,100 @@ +#include +#include +#include + +#include "phononcalc.h" + +namespace nb = nanobind; + +void py_get_phonons_at_gridpoints( + nb::ndarray<> py_frequencies, nb::ndarray<> py_eigenvectors, + nb::ndarray<> py_phonon_done, nb::ndarray<> py_grid_points, + nb::ndarray<> py_grid_address, nb::ndarray<> py_QDinv, nb::ndarray<> py_fc2, + nb::ndarray<> py_shortest_vectors_fc2, nb::ndarray<> py_multiplicity_fc2, + nb::ndarray<> py_positions_fc2, nb::ndarray<> py_masses_fc2, + nb::ndarray<> py_p2s_map_fc2, nb::ndarray<> py_s2p_map_fc2, + double unit_conversion_factor, nb::ndarray<> py_born_effective_charge, + nb::ndarray<> py_dielectric_constant, nb::ndarray<> py_reciprocal_lattice, + nb::ndarray<> py_q_direction, double nac_factor, nb::ndarray<> py_dd_q0, + nb::ndarray<> py_G_list, double lambda, long is_nac, long is_nac_q_zero, + long use_GL_NAC, const char *uplo) { + double(*born)[3][3]; + double(*dielectric)[3]; + double *q_dir; + double *freqs; + _lapack_complex_double *eigvecs; + char *phonon_done; + long *grid_points; + long(*grid_address)[3]; + double(*QDinv)[3]; + double *fc2; + double(*svecs_fc2)[3]; + long(*multi_fc2)[2]; + double(*positions_fc2)[3]; + double *masses_fc2; + long *p2s_fc2; + long *s2p_fc2; + double(*rec_lat)[3]; + double(*dd_q0)[2]; + double(*G_list)[3]; + long num_patom, num_satom, num_phonons, num_grid_points, num_G_points; + + freqs = (double *)py_frequencies.data(); + eigvecs = (_lapack_complex_double *)py_eigenvectors.data(); + phonon_done = (char *)py_phonon_done.data(); + grid_points = (long *)py_grid_points.data(); + grid_address = (long(*)[3])py_grid_address.data(); + QDinv = (double(*)[3])py_QDinv.data(); + fc2 = (double *)py_fc2.data(); + svecs_fc2 = (double(*)[3])py_shortest_vectors_fc2.data(); + multi_fc2 = (long(*)[2])py_multiplicity_fc2.data(); + masses_fc2 = (double *)py_masses_fc2.data(); + p2s_fc2 = (long *)py_p2s_map_fc2.data(); + s2p_fc2 = (long *)py_s2p_map_fc2.data(); + rec_lat = (double(*)[3])py_reciprocal_lattice.data(); + num_patom = (long)py_multiplicity_fc2.shape(1); + num_satom = (long)py_multiplicity_fc2.shape(0); + num_phonons = (long)py_frequencies.shape(0); + num_grid_points = (long)py_grid_points.shape(0); + + if (is_nac) { + born = (double(*)[3][3])py_born_effective_charge.data(); + dielectric = (double(*)[3])py_dielectric_constant.data(); + } else { + born = NULL; + dielectric = NULL; + } + + if (is_nac_q_zero) { + q_dir = (double *)py_q_direction.data(); + if (fabs(q_dir[0]) < 1e-10 && fabs(q_dir[1]) < 1e-10 && + fabs(q_dir[2]) < 1e-10) { + q_dir = NULL; + } + } else { + q_dir = NULL; + } + + if (use_GL_NAC) { + dd_q0 = (double(*)[2])py_dd_q0.data(); + G_list = (double(*)[3])py_G_list.data(); + num_G_points = (long)py_G_list.shape(0); + positions_fc2 = (double(*)[3])py_positions_fc2.data(); + } else { + dd_q0 = NULL; + G_list = NULL; + num_G_points = 0; + positions_fc2 = NULL; + } + + phcalc_get_phonons_at_gridpoints( + freqs, eigvecs, phonon_done, num_phonons, grid_points, num_grid_points, + grid_address, QDinv, fc2, svecs_fc2, multi_fc2, positions_fc2, + num_patom, num_satom, masses_fc2, p2s_fc2, s2p_fc2, + unit_conversion_factor, born, dielectric, rec_lat, q_dir, nac_factor, + dd_q0, G_list, num_G_points, lambda, uplo[0]); +} + +NB_MODULE(_phononcalc, m) { + m.def("phonons_at_gridpoints", py_get_phonons_at_gridpoints); +} diff --git a/c/phono3py.h b/c/phono3py.h index 1d9ad000..d6a2972f 100644 --- a/c/phono3py.h +++ b/c/phono3py.h @@ -35,6 +35,10 @@ #ifndef __phono3py_H__ #define __phono3py_H__ +#ifdef __cplusplus +extern "C" { +#endif + #include "phonoc_array.h" typedef struct { @@ -237,4 +241,9 @@ void ph3py_pinv_from_eigensolution(double *data, const double *eigvals, const long size, const double cutoff, const long pinv_method); long ph3py_get_max_threads(void); + +#ifdef __cplusplus +} +#endif + #endif diff --git a/c/phononcalc.h b/c/phononcalc.h index 89c24a46..1265903f 100644 --- a/c/phononcalc.h +++ b/c/phononcalc.h @@ -35,6 +35,10 @@ #ifndef __phononcalc_H__ #define __phononcalc_H__ +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { double re; double im; @@ -55,4 +59,8 @@ void phcalc_get_phonons_at_gridpoints( const double (*G_list)[3], const long num_G_points, const double lambda, const char uplo); +#ifdef __cplusplus +} +#endif + #endif diff --git a/cmake-format.py b/cmake-format.py new file mode 100644 index 00000000..4d509443 --- /dev/null +++ b/cmake-format.py @@ -0,0 +1,4 @@ +with section("format"): + disable = False + line_width = 85 + tab_size = 4 diff --git a/ctest/CMakeLists.txt b/ctest/CMakeLists.txt index a3658f4b..fec75cea 100644 --- a/ctest/CMakeLists.txt +++ b/ctest/CMakeLists.txt @@ -6,37 +6,37 @@ set(CMAKE_CXX_STANDARD_REQUIRED True) find_package(GTest) if(NOT GTest_FOUND) - # pthread (required for GoogleTest) - # https://stackoverflow.com/questions/1620918/cmake-and-libpthread - set(THREADS_PREFER_PTHREAD_FLAG ON) - find_package(Threads REQUIRED) + # pthread (required for GoogleTest) + # https://stackoverflow.com/questions/1620918/cmake-and-libpthread + set(THREADS_PREFER_PTHREAD_FLAG ON) + find_package(Threads REQUIRED) - # Fetch GoogleTest - include(FetchContent) + # Fetch GoogleTest + include(FetchContent) - # cmake-lint inline directives must be specified at body scope. See - # https://cmake-format.readthedocs.io/en/latest/lint-inline.html + # cmake-lint inline directives must be specified at body scope. See + # https://cmake-format.readthedocs.io/en/latest/lint-inline.html - # cmake-lint: disable=C0301 - FetchContent_Declare( - googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG 4fb7039fda3f6588c7ca9664176f8c9e0a023b4a) - FetchContent_MakeAvailable(googletest) + # cmake-lint: disable=C0301 + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG 4fb7039fda3f6588c7ca9664176f8c9e0a023b4a) + FetchContent_MakeAvailable(googletest) endif() foreach(testcase IN ITEMS test_gridsys test_niggli) - add_executable(${testcase} ${CMAKE_CURRENT_SOURCE_DIR}/${testcase}.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/utils.c) - target_link_libraries( - ${testcase} - PUBLIC gridsys - PRIVATE GTest::gtest GTest::gtest_main) - target_include_directories(${testcase} PUBLIC ${PROJECT_SOURCE_DIR}/c - ${CMAKE_CURRENT_SOURCE_DIR}) - gtest_discover_tests(${testcase}) + add_executable(${testcase} ${CMAKE_CURRENT_SOURCE_DIR}/${testcase}.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/utils.c) + target_link_libraries( + ${testcase} + PUBLIC gridsys + PRIVATE GTest::gtest GTest::gtest_main) + target_include_directories(${testcase} PUBLIC ${PROJECT_SOURCE_DIR}/c + ${CMAKE_CURRENT_SOURCE_DIR}) + gtest_discover_tests(${testcase}) endforeach() if(WITH_Fortran) - add_subdirectory(fortran) + add_subdirectory(fortran) endif() diff --git a/ctest/fortran/gridsysf/CMakeLists.txt b/ctest/fortran/gridsysf/CMakeLists.txt index 996f45b3..db66c4b3 100644 --- a/ctest/fortran/gridsysf/CMakeLists.txt +++ b/ctest/fortran/gridsysf/CMakeLists.txt @@ -7,6 +7,6 @@ set_target_properties(test_${NAME} PROPERTIES Fortran_MODULE_DIRECTORY ${LIB_MOD_DIR}) add_test( - NAME ${NAME} - COMMAND $ ${CMAKE_CURRENT_BINARY_DIR} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + NAME ${NAME} + COMMAND $ ${CMAKE_CURRENT_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/doc/changelog.md b/doc/changelog.md index 9fba0f68..77c32354 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -2,6 +2,12 @@ # Change Log +## Jul-8-2024: Version 3.3.0 + +- Build system of phono3py was renewed. Now nanobind, cmake, and + scikit-build-core are used for the building, and the receipt is written in + `CMakeLists.txt` and `pyproject.toml`. + ## Jun-29-2024: Version 3.2.0 - `--rd` and `--rd-fc2` options for generating random directional displacements. diff --git a/doc/conf.py b/doc/conf.py index ef0f8f99..ab73c002 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -58,9 +58,9 @@ # built documents. # # The short X.Y version. -version = "3.2" +version = "3.3" # The full version, including alpha/beta/rc tags. -release = "3.2.0" +release = "3.3.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/install.md b/doc/install.md index 16d64e77..f3103668 100644 --- a/doc/install.md +++ b/doc/install.md @@ -30,18 +30,23 @@ All dependent packages should be installed. (install_from_source_code)= ## Installation from source code -When installing phono3py using `setup.py` from the source code, a few libraries -are required before running `setup.py` script. +When installing phono3py from the source code, a few libraries are required +before running `pip install`. + +Note that at version 3.3.0, the build system of phono3py was modernized. +Nanobind, cmake, and scikit-build-core are used for the building. The receipt is +written in `CMakeLists.txt` and `pyproject.toml`. The old `setup.py` was +removed. + +If phono3py is compiled with a special compiler or special options, manual +modification of `CMakeLists.txt` may be needed. - {ref}`Linear algebra library `: BLAS, LAPACK, and LAPACKE - {ref}`OpenMP library `: For the multithreding support. These packages may be installed by the package manager of OS (e.g. `apt`) or conda environment. Automatic search of required libraries and flags that are -already on the system is performed by cmake. If cmake is installed on the -system, this automatic search is invoked as default. For the installation with -custom configurations without using cmake, the environment variable -`PHONO3PY_USE_CMAKE=false` has to be set. +already on the system is performed by cmake. (install_with_cmake)= ### Build with automatic search of library configurations by cmake @@ -56,57 +61,6 @@ See an example at {ref}`install_an_example`. In the standard output, flags and libraries found by cmake are shown. Please carefully check if those configurations are expected ones or not. -(install_custom)= -### Build with custom library configurations by `site.cfg` file - -Custom installation is achieved by creating `site.cfg` file on the same -directory as `setup.py`. Users will write configurations of compiler flags and -linked libraries in `site.cfg`. If `setup.py` finds `site.cfg`, the -configurations are used as the default configurations. If cmake is found in the -system, cmake tries to find required libraries and found configurations are -appended. To deactivate cmake's library search, the environment variable -`PHONO3PY_USE_CMAKE=false` has to be set before running the phono3py build: -``` -% export PHONO3PY_USE_CMAKE=false -``` -In previous versions, `site.cfg` was processed by numpy, -but from version 2.4.0, it is processed by script in `setup.py`. -`extra_link_args`, `extra_compile_args`, `extra_objects`, and `include_dirs` can -be specified. How they used is found at [setuptools web -site](https://setuptools.pypa.io/en/latest/userguide/ext_modules.html#extension-api-reference). - -In most cases, users want to enable multithreading support with OpenMP. Its -minimum setting with gcc as the compiler is: - -``` -extra_compile_args = -fopenmp -``` - -Additional configuration can be necessary. It is recommended first starting only -with `extra_compile_args = -fopenmp` and run `setup.py`, then check if phono3py -works properly or not without error or warning. When phono3py doesn't work with -the above setting, add another configuration one by one to test compilation. -Some examples are given below. - -For MKL (for gcc and clang), `site.cfg` - -``` -extra_compile_args = -fopenmp -``` - -For openblas and clang - -``` -extra_compile_args = -fopenmp -``` - -For openblas and gcc - -``` -extra_compile_args = -fopenmp -extra_link_args = -lgomp -``` - (install_an_example)= ## Installation instruction of latest development version of phono3py @@ -117,7 +71,8 @@ wrong python libraries can be imported. 1. Download miniforge Miniforge is downloaded at https://github.com/conda-forge/miniforge. The - detailed installation instruction is found in the same page. If usual conda or miniconda is used, the following `~/.condarc` setting is recommended: + detailed installation instruction is found in the same page. If usual conda + or miniconda is used, the following `~/.condarc` setting is recommended: ``` channel_priority: strict @@ -148,7 +103,7 @@ wrong python libraries can be imported. For x86-64 system: ```bash - % conda install numpy scipy h5py pyyaml matplotlib-base c-compiler "libblas=*=*mkl" spglib mkl-include cmake + % conda install numpy scipy h5py pyyaml matplotlib-base c-compiler cxx-compiler "libblas=*=*mkl" spglib mkl-include cmake ``` A libblas library can be chosen among `[openblas, mkl, blis, netlib]`. If @@ -161,7 +116,7 @@ wrong python libraries can be imported. For macOS ARM64 system, currently only openblas can be chosen: ```bash - % conda install numpy scipy h5py pyyaml matplotlib-base c-compiler spglib cmake openblas + % conda install numpy scipy h5py pyyaml matplotlib-base c-compiler cxx-compiler spglib cmake openblas ``` Note that using hdf5 files on NFS mounted file system, you may have to disable @@ -179,10 +134,8 @@ wrong python libraries can be imported. % git clone https://github.com/phonopy/phonopy.git % git clone https://github.com/phonopy/phono3py.git % cd phonopy - % git checkout develop % pip install -e . -vvv % cd ../phono3py - % git checkout develop % pip install -e . -vvv ``` @@ -215,23 +168,6 @@ Ubuntu package manager (`liblapacke` and `liblapacke-dev`): % sudo apt-get install liblapack-dev liblapacke-dev ``` -### Compiling Netlib LAPACKE - -The compilation procedure is found at the LAPACKE web site. After creating the -LAPACKE library, `liblapacke.a` (or the dynamic link library), `setup.py` must -be properly modified to link it. As an example, the procedure of compiling -LAPACKE is shown below. - -```bash -% tar xvfz lapack-3.6.0.tgz -% cd lapack-3.6.0 -% cp make.inc.example make.inc -% make lapackelib -``` - -BLAS, LAPACK, and LAPACKE, these all may have to be compiled with `-fPIC` option -to use it with python. - (install_openmp)= ## Multithreading and its controlling by C macro diff --git a/fortran/CMakeLists.txt b/fortran/CMakeLists.txt index cb8b6cf5..a02f1317 100644 --- a/fortran/CMakeLists.txt +++ b/fortran/CMakeLists.txt @@ -1,9 +1,9 @@ if(USE_OpenMP) - find_package( - OpenMP - COMPONENTS Fortran - REQUIRED) - set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${OpenMP_Fortran_FLAGS}") + find_package( + OpenMP + COMPONENTS Fortran + REQUIRED) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${OpenMP_Fortran_FLAGS}") endif() add_library(gridsysf_static STATIC gridsysf.f90) @@ -13,11 +13,11 @@ target_link_libraries(gridsysf_static PRIVATE gridsys_static) install(TARGETS gridsysf_static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) if(BUILD_SHARED_LIBRARIES) - add_library(gridsysf SHARED gridsysf.f90) - set_property(TARGET gridsysf PROPERTY VERSION ${PROJECT_VERSION}) - set_property(TARGET gridsysf PROPERTY SOVERSION ${soserial}) - target_link_libraries(gridsysf PUBLIC gridsys) - install(TARGETS gridsysf LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) + add_library(gridsysf SHARED gridsysf.f90) + set_property(TARGET gridsysf PROPERTY VERSION ${PROJECT_VERSION}) + set_property(TARGET gridsysf PROPERTY SOVERSION ${soserial}) + target_link_libraries(gridsysf PUBLIC gridsys) + install(TARGETS gridsysf LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() install(FILES ${CMAKE_CURRENT_BINARY_DIR}/gridsysf.mod diff --git a/phono3py/api_phono3py.py b/phono3py/api_phono3py.py index 42b83762..2be91174 100644 --- a/phono3py/api_phono3py.py +++ b/phono3py/api_phono3py.py @@ -2168,7 +2168,11 @@ def save(self, filename="phono3py_params.yaml", settings=None): with open(filename, "w") as w: w.write(str(ph3py_yaml)) - def develop_mlp(self, params: Optional[Union[PypolymlpParams, dict, str]] = None): + def develop_mlp( + self, + params: Optional[Union[PypolymlpParams, dict, str]] = None, + test_size: float = 0.1, + ): """Develop MLP of pypolymlp. Parameters @@ -2176,6 +2180,10 @@ def develop_mlp(self, params: Optional[Union[PypolymlpParams, dict, str]] = None params : PypolymlpParams or dict, optional Parameters for developing MLP. Default is None. When dict is given, PypolymlpParams instance is created from the dict. + test_size : float, optional + Training and test data are splitted by this ratio. test_size=0.1 + means the first 90% of the data is used for training and the rest + is used for test. Default is 0.1. """ if self._mlp_dataset is None: @@ -2189,7 +2197,7 @@ def develop_mlp(self, params: Optional[Union[PypolymlpParams, dict, str]] = None disps = self._mlp_dataset["displacements"] forces = self._mlp_dataset["forces"] energies = self._mlp_dataset["supercell_energies"] - n = int(len(disps) * 0.9) + n = int(len(disps) * (1 - test_size)) train_data = PypolymlpData( displacements=disps[:n], forces=forces[:n], supercell_energies=energies[:n] ) @@ -2230,7 +2238,9 @@ def evaluate_mlp(self): self.forces = forces def develop_phonon_mlp( - self, params: Optional[Union[PypolymlpParams, dict, str]] = None + self, + params: Optional[Union[PypolymlpParams, dict, str]] = None, + test_size: float = 0.1, ): """Develop MLP of pypolymlp for fc2. @@ -2239,6 +2249,10 @@ def develop_phonon_mlp( params : PypolymlpParams or dict, optional Parameters for developing MLP. Default is None. When dict is given, PypolymlpParams instance is created from the dict. + test_size : float, optional + Training and test data are splitted by this ratio. test_size=0.1 + means the first 90% of the data is used for training and the rest + is used for test. Default is 0.1. """ if self._phonon_mlp_dataset is None: @@ -2252,7 +2266,7 @@ def develop_phonon_mlp( disps = self._phonon_mlp_dataset["displacements"] forces = self._phonon_mlp_dataset["forces"] energies = self._phonon_mlp_dataset["supercell_energies"] - n = int(len(disps) * 0.9) + n = int(len(disps) * (1 - test_size)) train_data = PypolymlpData( displacements=disps[:n], forces=forces[:n], supercell_energies=energies[:n] ) diff --git a/phono3py/phonon/solver.py b/phono3py/phonon/solver.py index 983ee81e..ff2a76db 100644 --- a/phono3py/phonon/solver.py +++ b/phono3py/phonon/solver.py @@ -99,13 +99,25 @@ def run_phonon_solver_c( Lambda, ) = gonze_nac_dataset # Convergence parameter fc = gonze_fc + use_GL_NAC = True else: - positions = None - dd_q0 = None - G_list = None - Lambda = 0 + use_GL_NAC = False + positions = np.zeros(3) # dummy variable + dd_q0 = np.zeros(2) # dummy variable + G_list = np.zeros(3) # dummy variable + Lambda = 0 # dummy variable + if not dm.is_nac(): + born = np.zeros((3, 3)) # dummy variable + dielectric = np.zeros(3) # dummy variable fc = dm.force_constants + if nac_q_direction is None: + is_nac_q_zero = False + _nac_q_direction = np.zeros(3) + else: + is_nac_q_zero = True + _nac_q_direction = np.array(nac_q_direction, dtype="double") + assert grid_points.dtype == "int_" assert grid_points.flags.c_contiguous assert QDinv.dtype == "double" @@ -131,11 +143,14 @@ def run_phonon_solver_c( born, dielectric, rec_lattice, - nac_q_direction, - nac_factor, + _nac_q_direction, + float(nac_factor), dd_q0, G_list, - Lambda, + float(Lambda), + dm.is_nac() * 1, + is_nac_q_zero * 1, + use_GL_NAC * 1, lapack_zheev_uplo, ) diff --git a/scripts/phono3py b/phono3py/scripts/phono3py.py similarity index 97% rename from scripts/phono3py rename to phono3py/scripts/phono3py.py index dda1d230..194d611f 100755 --- a/scripts/phono3py +++ b/phono3py/scripts/phono3py.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # Copyright (C) 2011 Atsushi Togo # All rights reserved. # @@ -36,7 +34,9 @@ from phono3py.cui.phono3py_script import main -if __name__ == "__main__": + +def run(): + """Run phono3py script.""" argparse_control = { "fc_symmetry": False, "is_nac": False, diff --git a/scripts/phono3py-coleigplot b/phono3py/scripts/phono3py_coleigplot.py similarity index 98% rename from scripts/phono3py-coleigplot rename to phono3py/scripts/phono3py_coleigplot.py index 22d1894b..6f829860 100755 --- a/scripts/phono3py-coleigplot +++ b/phono3py/scripts/phono3py_coleigplot.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import argparse import os import sys @@ -139,5 +137,6 @@ def main(args: argparse.Namespace): plot(args) -if __name__ == "__main__": +def run(): + """Run phono3py-coleigplot script.""" main(get_options()) diff --git a/scripts/phono3py-kaccum b/phono3py/scripts/phono3py_kaccum.py similarity index 97% rename from scripts/phono3py-kaccum rename to phono3py/scripts/phono3py_kaccum.py index 0129ba8a..2ccd37fa 100755 --- a/scripts/phono3py-kaccum +++ b/phono3py/scripts/phono3py_kaccum.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # Copyright (C) 2021 Atsushi Togo # All rights reserved. # @@ -36,5 +34,7 @@ from phono3py.cui.kaccum_script import main -if __name__ == "__main__": + +def run(): + """Run phono3py-kaccum script.""" main() diff --git a/scripts/phono3py-kdeplot b/phono3py/scripts/phono3py_kdeplot.py similarity index 99% rename from scripts/phono3py-kdeplot rename to phono3py/scripts/phono3py_kdeplot.py index 184bbc88..d1913272 100755 --- a/scripts/phono3py-kdeplot +++ b/phono3py/scripts/phono3py_kdeplot.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import argparse import os import sys @@ -350,5 +348,6 @@ def main(args): plt.close(fig) -if __name__ == "__main__": +def run(): + """Run phono3py-kdeplot script.""" main(get_options()) diff --git a/scripts/phono3py-load b/phono3py/scripts/phono3py_load.py similarity index 97% rename from scripts/phono3py-load rename to phono3py/scripts/phono3py_load.py index 9dc5a633..140295dc 100755 --- a/scripts/phono3py-load +++ b/phono3py/scripts/phono3py_load.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # Copyright (C) 2020 Atsushi Togo # All rights reserved. # @@ -36,6 +34,8 @@ from phono3py.cui.phono3py_script import main -if __name__ == "__main__": + +def run(): + """Run phono3py-load script.""" argparse_control = {"fc_symmetry": True, "is_nac": True, "load_phono3py_yaml": True} main(**argparse_control) diff --git a/phono3py/version.py b/phono3py/version.py index a490a3d8..87c2d2f1 100644 --- a/phono3py/version.py +++ b/phono3py/version.py @@ -34,4 +34,4 @@ # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -__version__ = "3.2.0" +__version__ = "3.3.0" diff --git a/pyproject.toml b/pyproject.toml index 52340c86..6447ea50 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,60 @@ [build-system] -requires = ["setuptools", "wheel", "numpy"] +requires = ["scikit-build-core", "nanobind", "numpy"] +build-backend = "scikit_build_core.build" + +[project] +name = "phono3py" +dynamic = ["version"] +readme = { file = "README.md", content-type = "text/markdown" } +description = "This is the phono3py module." +authors = [{ name = "Atsushi Togo", email = "atztogo@gmail.com" }] +requires-python = ">=3.8" +dependencies = [ + "numpy>=1.17.0", + "scipy", + "PyYAML>=5.3", + "matplotlib>=2.2.2", + "h5py>=3.0", + "spglib>=2.3", + "phonopy>=2.26,<2.27", +] +license = { file = "LICENSE" } + +[project.urls] +Homepage = "https://phonopy.github.io/phono3py/" +Repository = "https://github.com/phonopy/phono3py" + +[project.scripts] +phono3py = "phono3py.scripts.phono3py:run" +phono3py-load = "phono3py.scripts.phono3py_load:run" +phono3py-coleigplot = "phono3py.scripts.phono3py_coleigplot:run" +phono3py-kaccum = "phono3py.scripts.phono3py_kaccum:run" +phono3py-kdeplot = "phono3py.scripts.phono3py_kdeplot:run" + + +[tool.scikit-build] +cmake.verbose = true +logging.level = "INFO" +metadata.version.provider = "scikit_build_core.metadata.setuptools_scm" +sdist.exclude = ["*"] +sdist.include = [ + "test", + "LICENSE", + "c", + "example", + "phono3py", + "pyproject.toml", + "CMakeLists.txt", + "README.md", +] + +[tool.scikit-build.cmake.define] +PHONO3PY_USE_MTBLAS = {env="PHONO3PY_USE_MTBLAS", default="ON"} +USE_CONDA_PATH = {env="USE_CONDA_PATH", default="ON"} +PHONO3PY_USE_OMP = {env="PHONO3PY_USE_OMP", default="ON"} + +[tool.setuptools_scm] +write_to = "phono3py/_version.py" [tool.ruff] line-length = 88 @@ -10,10 +65,8 @@ lint.select = [ "E", # pycodestyle-errors "D", # pydocstyle ] -lint.extend-ignore = [ - "D417", - "D100", -] +lint.extend-ignore = ["D417", "D100"] +exclude = ["cmake-format.py"] [tool.ruff.lint.pydocstyle] convention = "numpy" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 146789f8..00000000 --- a/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -numpy >= 1.17.0 -PyYAML >= 5.3 -matplotlib >= 2.2.2 -h5py >= 3.0 -phonopy >=2.25,<2.26 diff --git a/setup.cfg b/setup-legacy.cfg similarity index 100% rename from setup.cfg rename to setup-legacy.cfg diff --git a/setup.py b/setup-legacy.py similarity index 100% rename from setup.py rename to setup-legacy.py