Compare commits

...

211 Commits

Author SHA1 Message Date
Atsushi Togo ff95c4dd2e
Merge pull request #420 from phonopy/refactor
Merge CUI for pypolymlp to phonopy
2025-07-29 16:22:34 +09:00
Atsushi Togo 3ec495f05a Merge CUI for pypolymlp to phonopy 2025-07-29 16:11:59 +09:00
Atsushi Togo de2e6d3025
Merge pull request #419 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-07-29 09:21:58 +09:00
pre-commit-ci[bot] 2195be17f9
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.12.4 → v0.12.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.4...v0.12.5)
2025-07-28 20:57:00 +00:00
Atsushi Togo 499ba37b43 Update document on pypolymlp 2025-07-26 14:59:11 +09:00
Atsushi Togo 5e254fa516 Update document on pypolymlp 2025-07-26 14:52:32 +09:00
Atsushi Togo 8e7bc01229 Merge branch 'develop' 2025-07-22 16:15:29 +09:00
Atsushi Togo a12bb6becd
Merge pull request #418 from phonopy/release
Release v3.18.0
2025-07-22 16:06:34 +09:00
Atsushi Togo 21d4d86698 Avoid redundant calculation of fc2 2025-07-22 15:57:20 +09:00
Atsushi Togo b7a71c2883 Minor fix for reading polymlp.yaml 2025-07-22 15:34:55 +09:00
Atsushi Togo 006e63d799 Minor fix for reading polymlp.yaml 2025-07-22 15:18:40 +09:00
Atsushi Togo 5a14780e6b Set version 3.18.0 2025-07-22 15:13:54 +09:00
Atsushi Togo e736838528 Merge branch 'develop' of github.com:phonopy/phono3py into develop 2025-07-22 15:12:07 +09:00
Atsushi Togo 4181111479 Prevent phono3py-kaccum from reading POSCAR 2025-07-22 15:11:57 +09:00
Atsushi Togo baf34031eb
Merge pull request #416 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-07-22 14:23:52 +09:00
pre-commit-ci[bot] 69d6fcec75
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.12.3 → v0.12.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.3...v0.12.4)
2025-07-21 21:04:31 +00:00
Atsushi Togo 9ddbbbfa56 Very minor update 2025-07-21 17:21:47 +09:00
Atsushi Togo 12dc119f56 Update phonopy version dependency 2025-07-21 12:05:13 +09:00
Atsushi Togo e26f3ecbbd
Merge pull request #415 from phonopy/relax
Implement relaxation using pypolymlp in CUI
2025-07-20 19:28:08 +09:00
Atsushi Togo 3564186adc Implement relaxation using pypolymlp in CUI 2025-07-20 18:42:07 +09:00
Atsushi Togo cbcf9e84e5
Merge pull request #414 from phonopy/refactor
Refactoring
2025-07-19 19:15:26 +09:00
Atsushi Togo 9eb09dd01e Minor refactoring 2025-07-19 18:25:13 +09:00
Atsushi Togo 7dc202dde7 Further refactoring 2025-07-19 18:19:29 +09:00
Atsushi Togo dd9f626bb8 Set __all__ for imports in __init__.py 2025-07-19 17:22:08 +09:00
Atsushi Togo 630d09f174 Add from __future__ import annotations 2025-07-19 17:17:05 +09:00
Atsushi Togo 8d9e72c130 Minor typehint update 2025-07-19 17:13:30 +09:00
Atsushi Togo 096269a8b6 Refactoring 2025-07-19 17:11:28 +09:00
Atsushi Togo 35dd083b3a
Merge pull request #413 from phonopy/refactoring
Refactoring and adding typehints
2025-07-18 15:02:04 +09:00
Atsushi Togo 6eceedc3bb Add from __future__ import annotations 2025-07-18 14:53:37 +09:00
Atsushi Togo d67c4d81db Add from __future__ import annotations 2025-07-18 14:48:36 +09:00
Atsushi Togo 818ea508c8 Refactoring and adding typehints 2025-07-18 14:44:39 +09:00
Atsushi Togo 8568191817
Merge pull request #412 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-07-15 08:16:39 +09:00
pre-commit-ci[bot] 6a1239408a
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.12.2 → v0.12.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.2...v0.12.3)
2025-07-14 20:49:53 +00:00
Atsushi Togo fdc6aece55
Merge pull request #411 from phonopy/symmetrize-api
Update Phono3py.symmetrize_fc3
2025-07-08 19:22:07 +09:00
Atsushi Togo 7effdf6c26 Update test 2025-07-08 18:32:23 +09:00
Atsushi Togo cfcd64fb9f Add test for Phono3py.symmetrize_fc3 and symmetrize_fc2 2025-07-08 18:12:43 +09:00
Atsushi Togo 8488ed0424 Update Phono3py.symmetrize_fc3 2025-07-08 16:08:41 +09:00
Atsushi Togo c4c6d14ca2
Merge pull request #410 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-07-08 11:32:25 +09:00
pre-commit-ci[bot] 9825b8c171
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.12.1 → v0.12.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.1...v0.12.2)
2025-07-07 21:31:08 +00:00
Atsushi Togo 7e6e2ce628 Merge branch 'develop' 2025-07-05 10:46:58 +09:00
Atsushi Togo 47482e4116
Merge pull request #409 from phonopy/release
Set version 3.17.1
2025-07-05 10:45:15 +09:00
Atsushi Togo 9951f5bfaf Set version 3.17.1 2025-07-05 10:34:26 +09:00
Atsushi Togo 48105c5f52
Merge pull request #408 from phonopy/fix-407
Fix issue 407
2025-07-04 16:01:15 +09:00
Atsushi Togo 617a6e9162 Fix issue 407 2025-07-04 15:52:21 +09:00
Atsushi Togo 8eeb09d934
Merge pull request #406 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-07-01 10:57:37 +09:00
pre-commit-ci[bot] b4fa5458d5
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.13 → v0.12.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.13...v0.12.1)
2025-06-30 20:38:25 +00:00
Atsushi Togo d41603560d
Merge pull request #405 from phonopy/symmetrize-fc-methods
Add symmetrize_fc2 and symmetrize_fc3 in Phono3py class
2025-06-29 16:06:34 +09:00
Atsushi Togo 260e4a5e75 Add symmetrize_fc2 and symmetrize_fc3 in Phono3py class 2025-06-29 15:56:55 +09:00
Atsushi Togo 93a5e0ed3c Minor update of typehint 2025-06-27 16:12:18 +09:00
Atsushi Togo ad9cdcc64b Merge branch 'develop' 2025-06-26 19:25:00 +09:00
Atsushi Togo ea6b96d594
Merge pull request #404 from phonopy/release
Set version 3.17.0
2025-06-26 19:05:42 +09:00
Atsushi Togo dff1e08232 Set version 3.17.0 2025-06-26 18:56:55 +09:00
Atsushi Togo a001c65e6c Update dependency of phonopy version 2025-06-26 10:58:57 +09:00
Atsushi Togo 0269254fb9
Merge pull request #403 from phonopy/run-test
Commit to run tests on github
2025-06-25 15:38:59 +09:00
Atsushi Togo b42f1c374c Commit to run tests on github 2025-06-25 14:43:21 +09:00
Atsushi Togo 9441266bbb Call symfc project for FD when phonopy-load and fc-calculator is blank 2025-06-25 14:41:26 +09:00
Atsushi Togo ac2653147e
Merge pull request #402 from phonopy/symfc-projector
Use symfc-projector for FD when phono3py-load
2025-06-24 15:38:18 +09:00
Atsushi Togo 22fa0e1862 Use symfc-projector for FD when phono3py-load 2025-06-24 15:25:26 +09:00
Atsushi Togo 3ee42f3b81
Merge pull request #400 from phonopy/merge-nac-cui-routines
Merge cui traditional and phono3py-load rotines
2025-06-23 16:55:13 +09:00
Atsushi Togo 072e195940 Adjustment to let both CUI and phno3py.load work nicely 2025-06-23 16:25:31 +09:00
Atsushi Togo 7f44ce3594 Merge produe fc routines in CUI 2025-06-23 15:04:08 +09:00
Atsushi Togo bb1012784d Merge CUI routines to handle NAC 2025-06-23 11:08:27 +09:00
Atsushi Togo d4dcd0465e
Merge pull request #399 from phonopy/cell-info
Update following the change of collect_cell_info in phonopy
2025-06-23 10:50:18 +09:00
Atsushi Togo 1a243e2316 Add from __future__ import annotations 2025-06-22 17:36:34 +09:00
Atsushi Togo 166f012147 Update following the change of collect_cell_info in phonopy 2025-06-22 17:33:22 +09:00
Atsushi Togo 1426752ad8
Merge pull request #398 from phonopy/refactor-settings-py
Refactor settings.py following that of phonopy
2025-06-17 20:37:11 +09:00
Atsushi Togo 9b88998e3a Add from __future__ import annotations 2025-06-17 20:07:42 +09:00
Atsushi Togo 1441cbc155 Refactor settings.py following that of phonopy 2025-06-17 20:03:31 +09:00
Atsushi Togo 36ae0c1ffb Merge branch 'develop' of github.com:phonopy/phono3py into develop 2025-06-17 15:59:35 +09:00
Atsushi Togo 518b6feebf Update phonopy version dependency 2025-06-17 15:59:25 +09:00
Atsushi Togo 685d5f5e55
Merge pull request #397 from phonopy/tune-rec2normal
Performance optimization of reciprocal_to_normal in C
2025-06-14 18:24:21 +09:00
Atsushi Togo 55c334e6c2 Minor code clean-up 2025-06-14 18:15:03 +09:00
Atsushi Togo 26cac3aef5 Performance optimization of reciprocal_to_normal in C 2025-06-14 18:07:46 +09:00
Atsushi Togo 200e1b92a9
Merge pull request #396 from phonopy/number-estimation-factor
Add number_estimation_factor parameter for rd displacement generation
2025-06-13 14:01:49 +09:00
Atsushi Togo 788fab3cdf Avoid writing files in running tests 2025-06-13 13:43:04 +09:00
Atsushi Togo e02e7c9921 Update test_random_disps_agno2 2025-06-13 13:38:22 +09:00
Atsushi Togo d601796e05 Add number_estimation_factor parameter for rd displacement generation 2025-06-13 12:57:02 +09:00
Atsushi Togo bbd055d9b7 Merge branch 'develop' 2025-06-12 16:22:01 +09:00
Atsushi Togo dd60053a74
Merge pull request #395 from phonopy/release
Set version 3.16.0
2025-06-12 11:57:54 +09:00
Atsushi Togo c3a755ecb0 Set version 3.16.0 2025-06-12 11:31:02 +09:00
Atsushi Togo 1ec0116c10
Merge pull request #393 from phonopy/tune-recip2normal
Introduce memorization in reciprocal_to_normal for optimization
2025-06-11 12:57:59 +09:00
Atsushi Togo e4f37dba71 Zero clear of temporary array 2025-06-11 12:47:58 +09:00
Atsushi Togo cedd2477d8 Remove unused variables 2025-06-11 09:59:15 +09:00
Atsushi Togo 29cda14982 Replace memset 2025-06-11 09:56:42 +09:00
Atsushi Togo 5f75510927 Introduce memorization in eciprocal_to_normal for performance optimization 2025-06-11 09:44:34 +09:00
Atsushi Togo a3b8ad3dbd
Merge pull request #392 from phonopy/fix-distance-in-BZ
Fix distance calculation in BZ
2025-06-10 18:41:28 +09:00
Atsushi Togo 71bb34aa4a Fix distance calculation in BZ 2025-06-10 18:32:13 +09:00
Atsushi Togo ea1d083056
Merge pull request #391 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-06-10 10:28:21 +09:00
pre-commit-ci[bot] 13c83d6d6a
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.12 → v0.11.13](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.12...v0.11.13)
2025-06-09 20:42:14 +00:00
Atsushi Togo 2d30f9baf0 Fix comment in reciprocal_to_normal.c 2025-06-09 16:05:46 +09:00
Atsushi Togo 8bf63c030c
Merge pull request #390 from phonopy/fc3-cutoff-in-fdf5
Add fc3_cutoff entry in fc3.hdf5
2025-06-06 18:23:30 +09:00
Atsushi Togo 3eab5fbcbe Add fc3_cutoff entry in fc3.hdf5 2025-06-06 18:14:19 +09:00
Atsushi Togo 2e67d46379
Merge pull request #389 from phonopy/fc3-non-zero-indices
Run ph-ph interaction calculation with fc3-nonzero-indices
2025-06-06 13:21:17 +09:00
Atsushi Togo cbd410ac4c Run ph-ph interaction calculation with fc3-nonzero-indices 2025-06-06 13:05:44 +09:00
Atsushi Togo 748a9692aa
Merge pull request #388 from phonopy/refactor-read-write-fc3-fc2
Refactor reading and writing fc2 and fc3
2025-06-05 18:15:17 +09:00
Atsushi Togo 48f52c762c Refactor reading and writing fc2 and fc3 2025-06-05 18:07:18 +09:00
Atsushi Togo 83a96ebce6 Minor refactoring 2025-06-05 17:13:45 +09:00
Atsushi Togo ca30fcc101 Minor refactoring 2025-06-05 16:56:37 +09:00
Atsushi Togo c4a70293d2
Merge pull request #387 from phonopy/fc3-nonzero-indices
Write fc3_nonzero_indices in fc3.hdf5
2025-06-05 16:34:52 +09:00
Atsushi Togo 731ea60afe Update test_phono3py_load_with_typeII_dataset 2025-06-05 16:27:14 +09:00
Atsushi Togo 2732a1a0f0 Write fc3_nonzero_indices in fc3.hdf5 2025-06-05 16:23:26 +09:00
Atsushi Togo d202f2c27b
Merge pull request #386 from phonopy/fc3-nonzero-indices
Add Phono3py.fc3_nonzero_indices
2025-06-04 17:50:16 +09:00
Atsushi Togo 8d0db5c396 Add Phono3py.fc3_nonzero_indices 2025-06-04 17:40:45 +09:00
Atsushi Togo 03a26d1b6d Add self._fc3_nonzero_elems in API 2025-06-03 18:09:34 +09:00
Atsushi Togo 6a1a1a984a
Merge pull request #385 from phonopy/refactor-conductivity
Refactor conductivity
2025-06-03 15:40:42 +09:00
Atsushi Togo 238c537f31 [refactoring of conductivity] Wigner LBTE 2025-06-03 15:28:28 +09:00
Atsushi Togo 300e08d1d3 [refactoring of conductivity] Wigner RTA 2025-06-03 14:42:57 +09:00
Atsushi Togo 28dc226ee9
Merge pull request #384 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-06-03 10:51:48 +09:00
pre-commit-ci[bot] 91c9c5c619
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.11 → v0.11.12](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.11...v0.11.12)
2025-06-02 21:00:32 +00:00
Atsushi Togo 8be1b4cf95 [refactoring of conductivity] LBTE full-colmat 2025-06-02 17:00:09 +09:00
Atsushi Togo 18dac50c78 [refactoring of conductivity] LBTE 2025-06-02 08:48:54 +09:00
Atsushi Togo bcc4227415 [refactoring of conductivity] RTA 2025-06-02 08:26:59 +09:00
Atsushi Togo 39f4d09e24
Merge pull request #383 from phonopy/typehints
Improve type hints
2025-06-01 18:13:46 +09:00
Atsushi Togo 7122307413 Minor fix for type annotation 2025-06-01 09:20:15 +09:00
Atsushi Togo d0101dbb4b Improve type hints 2025-05-30 17:30:24 +09:00
Atsushi Togo 91ae3b89fc
Merge pull request #382 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-05-27 07:21:28 +09:00
pre-commit-ci[bot] 8a606ebf13
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.10 → v0.11.11](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.10...v0.11.11)
2025-05-26 20:43:46 +00:00
Atsushi Togo d86b3ed24d Update document to read pp-*.hdf5 and handling triplets 2025-05-20 19:30:21 +09:00
Atsushi Togo 9fc5186267 Update document to read pp-*.hdf5 and handling triplets 2025-05-20 19:20:24 +09:00
Atsushi Togo 16957da192
Merge pull request #381 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-05-20 07:24:37 +09:00
pre-commit-ci[bot] d8b2a2cd83
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.9 → v0.11.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.9...v0.11.10)
2025-05-19 20:45:28 +00:00
Atsushi Togo 8d0785c191 Minor fix 2025-05-17 18:56:51 +09:00
Atsushi Togo bacf5c2c5f Minor fix 2025-05-17 18:06:11 +09:00
Atsushi Togo 8ed85bff78
Merge pull request #379 from phonopy/symfc-memsize
Refine behaviour of symfc-memsize
2025-05-17 11:22:16 +09:00
Atsushi Togo e10b20260a Refine behaviour of symfc-memsize 2025-05-16 22:35:48 +09:00
Atsushi Togo 4a735f317e
Merge pull request #378 from phonopy/option-memsize
Add CUI option for rd=auto along with symfc memsize
2025-05-16 13:19:09 +09:00
Atsushi Togo cc0879dde0 Add tests 2025-05-16 08:54:22 +09:00
Atsushi Togo 426a193729 Support memsize displacement generation for MLP 2025-05-16 06:44:20 +09:00
Atsushi Togo f465e6ebab Refactoring of handling fc_calculator and cutoff input strings 2025-05-15 12:18:25 +09:00
Atsushi Togo e350a93a79 Add CUI option for rd=auto along with symfc memsize 2025-05-15 08:41:12 +09:00
Atsushi Togo 2a6239979c
Merge pull request #377 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-05-13 09:17:29 +09:00
pre-commit-ci[bot] d9e1a6c834
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.8 → v0.11.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.8...v0.11.9)
2025-05-12 20:38:08 +00:00
Atsushi Togo 8ccb13b081
Merge pull request #376 from phonopy/symfc
Update symfc wrapper to implement cutoff estimation by memory limit
2025-05-11 18:12:54 +09:00
Atsushi Togo e078306390 Update symfc wrapper to implement cutoff estimation by memory limit 2025-05-11 18:03:37 +09:00
Atsushi Togo 6521e406c5 Merge branch 'develop' of github.com:phonopy/phono3py into develop 2025-05-06 11:16:29 +09:00
Atsushi Togo 3ad068b34a Show pypolymlp version 2025-05-06 11:16:19 +09:00
Atsushi Togo 00d5ef756b
Merge pull request #375 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-05-06 11:00:06 +09:00
pre-commit-ci[bot] d5c88263d5
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.7 → v0.11.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.7...v0.11.8)
2025-05-05 20:56:40 +00:00
Atsushi Togo f0c26cec8a Merge branch 'develop' 2025-04-30 21:36:49 +09:00
Atsushi Togo 2e4c0b5d69
Merge pull request #374 from phonopy/release
Set version 3.15.1
2025-04-30 21:34:17 +09:00
Atsushi Togo a548f2269e Set version 3.15.1 2025-04-30 21:17:20 +09:00
Atsushi Togo da0bcbbceb
Merge pull request #373 from phonopy/KB_in_C
Remove unit conversion factor in C routines
2025-04-30 07:24:15 +09:00
Atsushi Togo 855ce1c3c2 Remove unit conversion factor in C routines 2025-04-29 22:31:05 +09:00
Atsushi Togo 6264dc5e35
Merge pull request #372 from phonopy/physical-unit
Migration of the physical units system
2025-04-29 19:56:36 +09:00
Atsushi Togo 7c0b4a2d0e Migration of the physical units system 2025-04-29 09:36:31 +09:00
Atsushi Togo c171367edd
Merge pull request #371 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-04-29 08:35:56 +09:00
pre-commit-ci[bot] ebde72e495
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.6 → v0.11.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.6...v0.11.7)
2025-04-28 20:38:58 +00:00
Atsushi Togo 834d644971
Merge pull request #370 from phonopy/kubo
Refactor kubo
2025-04-25 11:58:41 +09:00
Atsushi Togo aa2c973be3 Refactor kubo 2025-04-25 11:29:25 +09:00
Atsushi Togo bd04df7447
Merge pull request #369 from phonopy/refactor-conductivity
Refactoring of conductivity code
2025-04-25 09:42:24 +09:00
Atsushi Togo fe9d56135b Refactoring of conductivity code 2025-04-24 18:20:36 +09:00
Atsushi Togo fcefaf6fc9
Merge pull request #367 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-04-22 07:47:15 +09:00
pre-commit-ci[bot] 549b45aa7a
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.5 → v0.11.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.5...v0.11.6)
2025-04-21 20:28:14 +00:00
Atsushi Togo 16d2caae93
Merge pull request #366 from phonopy/fix-set_forces_and_nac_params
Fix _set_forces_and_nac_params
2025-04-21 16:20:26 +09:00
Atsushi Togo 2edbeadd3e Fix _set_forces_and_nac_params 2025-04-21 16:07:39 +09:00
Atsushi Togo fbdf8f9df7
Merge pull request #365 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-04-15 08:01:43 +09:00
pre-commit-ci[bot] 7c23c34d7c
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.4 → v0.11.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.4...v0.11.5)
2025-04-14 20:37:46 +00:00
Atsushi Togo f596ec86a1
Merge pull request #364 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-04-08 13:58:04 +09:00
pre-commit-ci[bot] 8d6f228d91
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.2 → v0.11.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.2...v0.11.4)
2025-04-07 21:21:14 +00:00
Atsushi Togo 285140c4ec
Merge pull request #363 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-03-25 10:10:59 +09:00
pre-commit-ci[bot] 29018ceb97
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.0 → v0.11.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.0...v0.11.2)
2025-03-24 20:47:42 +00:00
Atsushi Togo 3b77084931
Merge pull request #362 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-03-18 09:08:35 +09:00
pre-commit-ci[bot] 138103ba68
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.9.10 → v0.11.0](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.10...v0.11.0)
2025-03-17 20:55:25 +00:00
Atsushi Togo 204bd4db33
Merge pull request #361 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-03-11 16:01:05 +09:00
pre-commit-ci[bot] c7570cc4b8
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.9.9 → v0.9.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.9...v0.9.10)
2025-03-10 20:49:08 +00:00
Atsushi Togo 7806f7eb67 Merge branch 'develop' 2025-03-04 13:47:02 +09:00
Atsushi Togo 806bad7663
Merge pull request #360 from phonopy/release
Set version 3.15.0
2025-03-04 13:20:12 +09:00
Atsushi Togo 5817ef240c Set version 3.15.0 2025-03-04 13:10:42 +09:00
Atsushi Togo 613322f7e7
Merge pull request #359 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-03-04 08:05:16 +09:00
pre-commit-ci[bot] 359e76e0db
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.9.7 → v0.9.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.7...v0.9.9)
2025-03-03 21:26:22 +00:00
Atsushi Togo b22639ee1d Update pyrpoject.toml 2025-03-03 12:13:38 +09:00
Atsushi Togo 02a089ce91
Merge pull request #358 from phonopy/pypoylymlp-yaml
Pypoylymlp yaml
2025-03-03 12:07:53 +09:00
Atsushi Togo d7cb66417f Update pypolymlp doc 2025-03-03 11:19:45 +09:00
Atsushi Togo 33827f7210 Update for pypolymlp v0.9 2025-03-03 10:37:37 +09:00
Atsushi Togo 7a2b54faa7 Merge branch 'develop' 2025-03-01 18:29:38 +09:00
Atsushi Togo 6be93e7953
Merge pull request #357 from phonopy/release
Set version 3.14.1
2025-03-01 18:06:10 +09:00
Atsushi Togo 88469e0a83 Restrict pypolymlp<0.9 in github action tests 2025-03-01 17:50:22 +09:00
Atsushi Togo 8dac418ffc Set version 3.14.1 2025-03-01 16:49:15 +09:00
Atsushi Togo d15a5ec8ec
Merge pull request #356 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-02-25 11:55:42 +09:00
pre-commit-ci[bot] 0d6549b2e8
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.9.6 → v0.9.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.6...v0.9.7)
2025-02-24 20:39:05 +00:00
Atsushi Togo 088651931c
Merge pull request #354 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-02-11 10:50:30 +09:00
pre-commit-ci[bot] cb4cd068de
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.9.4 → v0.9.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.4...v0.9.6)
2025-02-11 00:05:08 +00:00
Atsushi Togo 91d43a535d
Merge pull request #353 from phonopy/refactor-fcsolver
Refactor fcsolver
2025-02-08 22:51:46 +09:00
Atsushi Togo e0fc1dfa31 Refactoring of fc solver 2025-02-08 22:40:33 +09:00
Atsushi Togo f12260fd4a Refactoring of fc solver 2025-02-08 20:08:58 +09:00
Atsushi Togo 5bcb753357 Merge branch 'develop' 2025-02-07 19:16:44 +09:00
Atsushi Togo 01bffc756d
Merge pull request #352 from phonopy/release
Set version 3.14.0
2025-02-07 18:47:51 +09:00
Atsushi Togo 482aec7bd8 Set version 3.14.0 2025-02-07 18:39:22 +09:00
Atsushi Togo 948faad549
Merge pull request #351 from phonopy/estimate-symfc-mem
Memory usage estimation for fc3 calculation using symfc
2025-02-06 16:05:38 +09:00
Atsushi Togo 8687e8eeb9 Limit --symfc-memshow option for phono3py-load 2025-02-06 15:47:00 +09:00
Atsushi Togo b70bb6ced4 --symfc-memshow option 2025-02-06 15:42:59 +09:00
Atsushi Togo c7c680df86
Merge pull request #348 from janosh/typos
Fix typos and add `codespell` `pre-commit` hook to catch future typos
2025-02-06 09:17:53 +09:00
Atsushi Togo a4ae4d05cd Fix .pre-commit-config.yaml 2025-02-06 09:12:14 +09:00
Janosh Riebesell e0e10db48c
Merge branch 'develop' into typos 2025-02-05 06:59:22 -05:00
Janosh Riebesell fc43730807 restore quotes in yaml config args 2025-02-05 06:25:56 -05:00
Janosh Riebesell e41b86877e missed some more 2025-02-05 05:50:52 -05:00
Janosh Riebesell 9145e47ea1 missed some 2025-02-05 05:47:27 -05:00
Janosh Riebesell 692dcce073 address @atztogo PR comments 2025-02-05 05:41:32 -05:00
Atsushi Togo 1fb5cb4eb9 Merge branch 'develop' 2025-02-05 14:50:49 +09:00
Atsushi Togo c49cfd7a64
Merge pull request #349 from phonopy/release
Set version 3.13.0
2025-02-05 14:44:51 +09:00
Atsushi Togo f2b7abde58 Set version 3.13.0 2025-02-05 14:33:53 +09:00
Atsushi Togo 40206bb1b8 Fix overwriting fc3 calc opts by cutoff-pair 2025-02-05 14:31:52 +09:00
Atsushi Togo 4144d97eb4 Update phonopy version dependency 2025-02-05 12:03:06 +09:00
Janosh Riebesell ece67a3201 fix typos and add codespell pre-commit hooks to catch future typos 2025-02-04 13:41:45 -05:00
Janosh Riebesell 00fb3b41f0 auto-format .pre-commit-config.yaml 2025-02-04 13:24:55 -05:00
Atsushi Togo fa6783d3ad
Merge pull request #347 from phonopy/update-rd-test
Update auto random displacements following the change in phonopy
2025-02-04 15:40:51 +09:00
Atsushi Togo 38ecb67988 Update auto random displacements following the change in phonopy 2025-02-04 15:30:03 +09:00
Atsushi Togo d8c0a6f999
Merge pull request #346 from phonopy/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2025-02-04 10:14:38 +09:00
pre-commit-ci[bot] 4b07cb1563
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.9.3 → v0.9.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.3...v0.9.4)
2025-02-04 00:59:19 +00:00
Atsushi Togo d658273c70 Merge branch 'make-wheel-test' into develop 2025-02-01 16:29:43 +09:00
Atsushi Togo c3447376ee Update github action to include windows wheel build 2025-02-01 16:19:25 +09:00
124 changed files with 10431 additions and 8413 deletions

View File

@ -24,7 +24,7 @@ jobs:
run: |
conda activate test
conda install --yes python=${{ matrix.python-version }}
conda install --yes matplotlib-base pyyaml "libblas=*=*mkl" mkl-include h5py scipy pytest spglib alm cmake c-compiler cxx-compiler pypolymlp
conda install --yes matplotlib-base pyyaml "libblas=*=*mkl" mkl-include h5py scipy pytest spglib alm cmake c-compiler cxx-compiler "pypolymlp<0.9"
- name: Install symfc develop branch
run: |
conda activate test

View File

@ -24,7 +24,7 @@ jobs:
run: |
conda activate test
conda install --yes python=${{ matrix.python-version }}
conda install --yes matplotlib-base pyyaml "libblas=*=*mkl" mkl-include h5py scipy pytest spglib alm cmake c-compiler cxx-compiler pypolymlp
conda install --yes matplotlib-base pyyaml "libblas=*=*mkl" mkl-include h5py scipy pytest spglib alm cmake c-compiler cxx-compiler "pypolymlp<0.9"
- name: Install symfc develop branch
run: |
conda activate test

View File

@ -24,7 +24,7 @@ jobs:
run: |
conda activate test
conda install --yes python=${{ matrix.python-version }}
conda install --yes matplotlib-base pyyaml "libblas=*=*mkl" mkl-include h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler cxx-compiler pypolymlp
conda install --yes matplotlib-base pyyaml "libblas=*=*mkl" mkl-include h5py scipy pytest codecov pytest-cov spglib alm cmake c-compiler cxx-compiler "pypolymlp<0.9"
- name: Install symfc develop branch
run: |
conda activate test

View File

@ -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 scipy pytest spglib alm cmake c-compiler cxx-compiler pypolymlp
conda install --yes matplotlib-base pyyaml "libblas=*=*openblas" openblas h5py scipy pytest spglib alm cmake c-compiler cxx-compiler "pypolymlp<0.9"
- name: Install symfc develop branch
run: |
conda activate test

View File

@ -25,7 +25,7 @@ jobs:
run: |
conda activate test
conda install --yes python=${{ matrix.python-version }}
conda install --yes matplotlib-base pyyaml h5py "numpy>=2.1" scipy pytest spglib alm cmake c-compiler cxx-compiler pypolymlp
conda install --yes matplotlib-base pyyaml h5py "numpy>=2.1" scipy pytest spglib alm cmake c-compiler cxx-compiler "pypolymlp<0.9"
- name: Install dependent packages for python == 3.9
if: ${{ matrix.python-version == 3.9 }}
run: |

View File

@ -12,8 +12,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest]
# os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-latest]
os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4

View File

@ -1,45 +1,55 @@
# See https://pre-commit.com for more informatio
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
exclude: ^example/AlN-LDA/
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
exclude: ^example/AlN-LDA/
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.3
hooks:
- id: ruff
args: [ "--fix", "--show-fixes" ]
- id: ruff-format
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.12.5
hooks:
- id: ruff
args: [ "--fix", "--show-fixes" ]
- id: ruff-format
- repo: https://github.com/Takishima/cmake-pre-commit-hooks
rev: v1.9.6
hooks:
- id: clang-format
args:
- '-B_build-pre-commit'
- '-DWITH_Fortran=ON'
- '-DWITH_TESTS=ON'
- '-i'
stages: [manual]
- id: clang-tidy
args:
- '-B_build-pre-commit'
- '-DWITH_Fortran=ON'
- '-DWITH_TESTS=ON'
# - '--'
# - '-I/Users/togo/.miniforge/envs/dev/include'
# - '-I/Users/togo/.miniforge/envs/dev/include/python3.10'
# - '-I/Users/togo/.miniforge/envs/dev/lib/python3.10/site-packages/numpy/core/include'
stages: [manual]
- repo: https://github.com/Takishima/cmake-pre-commit-hooks
rev: v1.9.6
hooks:
- id: clang-format
args:
- "-B_build-pre-commit"
- "-DWITH_Fortran=ON"
- "-DWITH_TESTS=ON"
- "-i"
stages: [manual]
- id: clang-tidy
args:
- "-B_build-pre-commit"
- "-DWITH_Fortran=ON"
- "-DWITH_TESTS=ON"
# "- --"
# "- -I/Users/togo/.miniforge/envs/dev/include"
# "- -I/Users/togo/.miniforge/envs/dev/include/python3.10"
# "- -I/Users/togo/.miniforge/envs/dev/lib/python3.10/site-packages/numpy/core/include"
stages: [manual]
- repo: https://github.com/cheshirekow/cmake-format-precommit
rev: v0.6.13
hooks:
- id: cmake-format
- id: cmake-lint
- repo: https://github.com/cheshirekow/cmake-format-precommit
rev: v0.6.13
hooks:
- id: cmake-format
- id: cmake-lint
- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
hooks:
- id: codespell
stages: [pre-commit, commit-msg]
args:
- --ignore-words-list
- "te,groth,skelton,inout,mater"
- --check-filenames

View File

@ -50,30 +50,30 @@ static Darray *convert_to_darray(nb::ndarray<> npyary) {
// 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, int64_t symmetrize_fc3_q,
int64_t make_r0_average, nb::ndarray<> py_all_shortest,
double cutoff_frequency, int64_t openmp_per_triplets) {
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_fc3_nonzero_indices, 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,
int64_t symmetrize_fc3_q, int64_t make_r0_average,
nb::ndarray<> py_all_shortest, double cutoff_frequency,
int64_t openmp_per_triplets) {
Darray *fc3_normal_squared;
Darray *freqs;
_lapack_complex_double *eigvecs;
int64_t(*triplets)[3];
int64_t (*triplets)[3];
int64_t num_triplets;
char *g_zero;
int64_t(*bz_grid_addresses)[3];
int64_t (*bz_grid_addresses)[3];
int64_t *D_diag;
int64_t(*Q)[3];
int64_t (*Q)[3];
double *fc3;
double(*svecs)[3];
int64_t(*multi)[2];
char *fc3_nonzero_indices;
double (*svecs)[3];
int64_t (*multi)[2];
double *masses;
char *all_shortest;
int64_t *p2s;
@ -88,23 +88,24 @@ void py_get_interaction(nb::ndarray<> py_fc3_normal_squared,
/* 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 = (int64_t(*)[3])py_triplets.data();
triplets = (int64_t (*)[3])py_triplets.data();
num_triplets = (int64_t)py_triplets.shape(0);
g_zero = (char *)py_g_zero.data();
bz_grid_addresses = (int64_t(*)[3])py_bz_grid_addresses.data();
bz_grid_addresses = (int64_t (*)[3])py_bz_grid_addresses.data();
D_diag = (int64_t *)py_D_diag.data();
Q = (int64_t(*)[3])py_Q.data();
Q = (int64_t (*)[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();
fc3_nonzero_indices = (char *)py_fc3_nonzero_indices.data();
svecs = (double (*)[3])py_svecs.data();
for (i = 0; i < 2; i++) {
multi_dims[i] = py_multi.shape(i);
}
multi = (int64_t(*)[2])py_multi.data();
multi = (int64_t (*)[2])py_multi.data();
masses = (double *)py_masses.data();
p2s = (int64_t *)py_p2s_map.data();
s2p = (int64_t *)py_s2p_map.data();
@ -113,9 +114,10 @@ void py_get_interaction(nb::ndarray<> py_fc3_normal_squared,
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);
fc3_nonzero_indices, 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;
@ -129,76 +131,80 @@ void py_get_pp_collision(
nb::ndarray<> py_triplets, nb::ndarray<> py_triplet_weights,
nb::ndarray<> py_bz_grid_addresses, nb::ndarray<> py_bz_map,
int64_t 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, int64_t is_NU,
int64_t symmetrize_fc3_q, int64_t make_r0_average,
nb::ndarray<> py_fc3, nb::ndarray<> py_fc3_nonzero_indices,
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_THz,
int64_t is_NU, int64_t symmetrize_fc3_q, int64_t make_r0_average,
nb::ndarray<> py_all_shortest, double cutoff_frequency,
int64_t openmp_per_triplets) {
double *gamma;
int64_t(*relative_grid_address)[4][3];
int64_t (*relative_grid_address)[4][3];
double *frequencies;
_lapack_complex_double *eigenvectors;
int64_t(*triplets)[3];
int64_t (*triplets)[3];
int64_t num_triplets;
int64_t *triplet_weights;
int64_t(*bz_grid_addresses)[3];
int64_t (*bz_grid_addresses)[3];
int64_t *bz_map;
int64_t *D_diag;
int64_t(*Q)[3];
int64_t (*Q)[3];
double *fc3;
double(*svecs)[3];
int64_t(*multi)[2];
char *fc3_nonzero_indices;
double (*svecs)[3];
int64_t (*multi)[2];
double *masses;
int64_t *p2s;
int64_t *s2p;
Larray *band_indices;
Darray *temperatures;
Darray *temperatures_THz;
char *all_shortest;
int64_t multi_dims[2];
int64_t i;
int64_t is_compact_fc3;
gamma = (double *)py_gamma.data();
relative_grid_address = (int64_t(*)[4][3])py_relative_grid_address.data();
relative_grid_address = (int64_t (*)[4][3])py_relative_grid_address.data();
frequencies = (double *)py_frequencies.data();
eigenvectors = (_lapack_complex_double *)py_eigenvectors.data();
triplets = (int64_t(*)[3])py_triplets.data();
triplets = (int64_t (*)[3])py_triplets.data();
num_triplets = (int64_t)py_triplets.shape(0);
triplet_weights = (int64_t *)py_triplet_weights.data();
bz_grid_addresses = (int64_t(*)[3])py_bz_grid_addresses.data();
bz_grid_addresses = (int64_t (*)[3])py_bz_grid_addresses.data();
bz_map = (int64_t *)py_bz_map.data();
D_diag = (int64_t *)py_D_diag.data();
Q = (int64_t(*)[3])py_Q.data();
Q = (int64_t (*)[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();
fc3_nonzero_indices = (char *)py_fc3_nonzero_indices.data();
svecs = (double (*)[3])py_svecs.data();
for (i = 0; i < 2; i++) {
multi_dims[i] = py_multi.shape(i);
}
multi = (int64_t(*)[2])py_multi.data();
multi = (int64_t (*)[2])py_multi.data();
masses = (double *)py_masses.data();
p2s = (int64_t *)py_p2s_map.data();
s2p = (int64_t *)py_s2p_map.data();
band_indices = convert_to_larray(py_band_indices);
temperatures = convert_to_darray(py_temperatures);
temperatures_THz = convert_to_darray(py_temperatures_THz);
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);
D_diag, Q, fc3, fc3_nonzero_indices, is_compact_fc3, svecs, multi_dims,
multi, masses, p2s, s2p, band_indices, temperatures_THz, 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;
free(temperatures_THz);
temperatures_THz = NULL;
}
void py_get_pp_collision_with_sigma(
@ -206,29 +212,31 @@ void py_get_pp_collision_with_sigma(
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_Q, nb::ndarray<> py_fc3,
nb::ndarray<> py_fc3_nonzero_indices, 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, int64_t is_NU, int64_t symmetrize_fc3_q,
nb::ndarray<> py_temperatures_THz, int64_t is_NU, int64_t symmetrize_fc3_q,
int64_t make_r0_average, nb::ndarray<> py_all_shortest,
double cutoff_frequency, int64_t openmp_per_triplets) {
double *gamma;
double *frequencies;
_lapack_complex_double *eigenvectors;
int64_t(*triplets)[3];
int64_t (*triplets)[3];
int64_t num_triplets;
int64_t *triplet_weights;
int64_t(*bz_grid_addresses)[3];
int64_t (*bz_grid_addresses)[3];
int64_t *D_diag;
int64_t(*Q)[3];
int64_t (*Q)[3];
double *fc3;
double(*svecs)[3];
int64_t(*multi)[2];
char *fc3_nonzero_indices;
double (*svecs)[3];
int64_t (*multi)[2];
double *masses;
int64_t *p2s;
int64_t *s2p;
Larray *band_indices;
Darray *temperatures;
Darray *temperatures_THz;
char *all_shortest;
int64_t multi_dims[2];
int64_t i;
@ -237,47 +245,48 @@ void py_get_pp_collision_with_sigma(
gamma = (double *)py_gamma.data();
frequencies = (double *)py_frequencies.data();
eigenvectors = (_lapack_complex_double *)py_eigenvectors.data();
triplets = (int64_t(*)[3])py_triplets.data();
triplets = (int64_t (*)[3])py_triplets.data();
num_triplets = (int64_t)py_triplets.shape(0);
triplet_weights = (int64_t *)py_triplet_weights.data();
bz_grid_addresses = (int64_t(*)[3])py_bz_grid_addresses.data();
bz_grid_addresses = (int64_t (*)[3])py_bz_grid_addresses.data();
D_diag = (int64_t *)py_D_diag.data();
Q = (int64_t(*)[3])py_Q.data();
Q = (int64_t (*)[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();
fc3_nonzero_indices = (char *)py_fc3_nonzero_indices.data();
svecs = (double (*)[3])py_svecs.data();
for (i = 0; i < 2; i++) {
multi_dims[i] = py_multi.shape(i);
}
multi = (int64_t(*)[2])py_multi.data();
multi = (int64_t (*)[2])py_multi.data();
masses = (double *)py_masses.data();
p2s = (int64_t *)py_p2s_map.data();
s2p = (int64_t *)py_s2p_map.data();
band_indices = convert_to_larray(py_band_indices);
temperatures = convert_to_darray(py_temperatures);
temperatures_THz = convert_to_darray(py_temperatures_THz);
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);
fc3_nonzero_indices, is_compact_fc3, svecs, multi_dims, multi, masses,
p2s, s2p, band_indices, temperatures_THz, 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;
free(temperatures_THz);
temperatures_THz = 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_frequencies, double temperature_THz, nb::ndarray<> py_g,
nb::ndarray<> py_g_zero, double cutoff_frequency,
int64_t frequency_point_index) {
Darray *fc3_normal_squared;
@ -285,7 +294,7 @@ void py_get_imag_self_energy_with_g(
double *g;
char *g_zero;
double *frequencies;
int64_t(*triplets)[3];
int64_t (*triplets)[3];
int64_t *triplet_weights;
int64_t num_frequency_points;
@ -294,13 +303,13 @@ void py_get_imag_self_energy_with_g(
g = (double *)py_g.data();
g_zero = (char *)py_g_zero.data();
frequencies = (double *)py_frequencies.data();
triplets = (int64_t(*)[3])py_triplets.data();
triplets = (int64_t (*)[3])py_triplets.data();
triplet_weights = (int64_t *)py_triplet_weights.data();
num_frequency_points = (int64_t)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,
g_zero, temperature_THz, cutoff_frequency, num_frequency_points,
frequency_point_index);
free(fc3_normal_squared);
@ -312,7 +321,7 @@ void py_get_detailed_imag_self_energy_with_g(
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 temperature_THz, nb::ndarray<> py_g, nb::ndarray<> py_g_zero,
double cutoff_frequency) {
Darray *fc3_normal_squared;
double *gamma_detail;
@ -321,9 +330,9 @@ void py_get_detailed_imag_self_energy_with_g(
double *g;
char *g_zero;
double *frequencies;
int64_t(*triplets)[3];
int64_t (*triplets)[3];
int64_t *triplet_weights;
int64_t(*bz_grid_addresses)[3];
int64_t (*bz_grid_addresses)[3];
fc3_normal_squared = convert_to_darray(py_fc3_normal_squared);
gamma_detail = (double *)py_gamma_detail.data();
@ -332,14 +341,14 @@ void py_get_detailed_imag_self_energy_with_g(
g = (double *)py_g.data();
g_zero = (char *)py_g_zero.data();
frequencies = (double *)py_frequencies.data();
triplets = (int64_t(*)[3])py_triplets.data();
triplets = (int64_t (*)[3])py_triplets.data();
triplet_weights = (int64_t *)py_triplet_weights.data();
bz_grid_addresses = (int64_t(*)[3])py_bz_grid_addresses.data();
bz_grid_addresses = (int64_t (*)[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);
triplets, triplet_weights, bz_grid_addresses, g, g_zero,
temperature_THz, cutoff_frequency);
free(fc3_normal_squared);
fc3_normal_squared = NULL;
@ -349,25 +358,25 @@ 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 temperature_THz, double epsilon, double unit_conversion_factor,
double cutoff_frequency) {
Darray *fc3_normal_squared;
double *shift;
double *frequencies;
int64_t *band_indices;
int64_t(*triplets)[3];
int64_t (*triplets)[3];
int64_t *triplet_weights;
fc3_normal_squared = convert_to_darray(py_fc3_normal_squared);
shift = (double *)py_shift.data();
frequencies = (double *)py_frequencies.data();
band_indices = (int64_t *)py_band_indices.data();
triplets = (int64_t(*)[3])py_triplets.data();
triplets = (int64_t (*)[3])py_triplets.data();
triplet_weights = (int64_t *)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,
triplet_weights, epsilon, temperature_THz, unit_conversion_factor,
cutoff_frequency);
free(fc3_normal_squared);
@ -378,26 +387,26 @@ 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,
nb::ndarray<> py_band_indices, double temperature_THz, double epsilon,
double unit_conversion_factor, double cutoff_frequency) {
Darray *fc3_normal_squared;
double *shift;
double *frequencies;
int64_t *band_indices;
int64_t(*triplets)[3];
int64_t (*triplets)[3];
int64_t *triplet_weights;
fc3_normal_squared = convert_to_darray(py_fc3_normal_squared);
shift = (double *)py_shift.data();
frequencies = (double *)py_frequencies.data();
band_indices = (int64_t *)py_band_indices.data();
triplets = (int64_t(*)[3])py_triplets.data();
triplets = (int64_t (*)[3])py_triplets.data();
triplet_weights = (int64_t *)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);
triplets, triplet_weights, epsilon, temperature_THz,
unit_conversion_factor, cutoff_frequency);
free(fc3_normal_squared);
fc3_normal_squared = NULL;
@ -408,13 +417,13 @@ void py_get_collision_matrix(
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 temperature_THz, double unit_conversion_factor,
double cutoff_frequency) {
Darray *fc3_normal_squared;
double *collision_matrix;
double *g;
double *frequencies;
int64_t(*triplets)[3];
int64_t (*triplets)[3];
int64_t *triplets_map;
int64_t *map_q;
int64_t *rotated_grid_points;
@ -425,7 +434,7 @@ void py_get_collision_matrix(
collision_matrix = (double *)py_collision_matrix.data();
g = (double *)py_g.data();
frequencies = (double *)py_frequencies.data();
triplets = (int64_t(*)[3])py_triplets.data();
triplets = (int64_t (*)[3])py_triplets.data();
triplets_map = (int64_t *)py_triplets_map.data();
num_gp = (int64_t)py_triplets_map.shape(0);
map_q = (int64_t *)py_map_q.data();
@ -440,7 +449,7 @@ void py_get_collision_matrix(
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,
num_ir_gp, num_gp, num_rot, temperature_THz,
unit_conversion_factor, cutoff_frequency);
free(fc3_normal_squared);
@ -450,13 +459,14 @@ void py_get_collision_matrix(
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) {
nb::ndarray<> py_triplets_map, nb::ndarray<> py_map_q,
double temperature_THz, double unit_conversion_factor,
double cutoff_frequency) {
Darray *fc3_normal_squared;
double *collision_matrix;
double *g;
double *frequencies;
int64_t(*triplets)[3];
int64_t (*triplets)[3];
int64_t *triplets_map;
int64_t num_gp;
int64_t *map_q;
@ -465,14 +475,14 @@ void py_get_reducible_collision_matrix(
collision_matrix = (double *)py_collision_matrix.data();
g = (double *)py_g.data();
frequencies = (double *)py_frequencies.data();
triplets = (int64_t(*)[3])py_triplets.data();
triplets = (int64_t (*)[3])py_triplets.data();
triplets_map = (int64_t *)py_triplets_map.data();
num_gp = (int64_t)py_triplets_map.shape(0);
map_q = (int64_t *)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,
triplets_map, map_q, g, num_gp, temperature_THz, unit_conversion_factor,
cutoff_frequency);
free(fc3_normal_squared);
@ -544,21 +554,21 @@ 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 (*fc3)[3][3][3];
double (*delta_fc2s)[3][3];
double *inv_U;
double(*site_sym_cart)[3][3];
double (*site_sym_cart)[3][3];
int64_t *rot_map_syms;
int64_t num_atom, num_disp, num_site_sym;
/* (num_atom, num_atom, 3, 3, 3) */
fc3 = (double(*)[3][3][3])py_fc3.data();
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();
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();
site_sym_cart = (double (*)[3][3])py_site_sym_cart.data();
/* (n_sym, natom) */
rot_map_syms = (int64_t *)py_rot_map_syms.data();
@ -695,11 +705,11 @@ void py_transpose_compact_fc3(nb::ndarray<> py_fc3,
void py_get_thm_relative_grid_address(nb::ndarray<> py_relative_grid_address,
nb::ndarray<> py_reciprocal_lattice_py) {
int64_t(*relative_grid_address)[4][3];
double(*reciprocal_lattice)[3];
int64_t (*relative_grid_address)[4][3];
double (*reciprocal_lattice)[3];
relative_grid_address = (int64_t(*)[4][3])py_relative_grid_address.data();
reciprocal_lattice = (double(*)[3])py_reciprocal_lattice_py.data();
relative_grid_address = (int64_t (*)[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);
}
@ -714,18 +724,18 @@ void py_get_neighboring_grid_points(nb::ndarray<> py_relative_grid_points,
int64_t *relative_grid_points;
int64_t *grid_points;
int64_t num_grid_points, num_relative_grid_address;
int64_t(*relative_grid_address)[3];
int64_t (*relative_grid_address)[3];
int64_t *D_diag;
int64_t(*bz_grid_address)[3];
int64_t (*bz_grid_address)[3];
int64_t *bz_map;
relative_grid_points = (int64_t *)py_relative_grid_points.data();
grid_points = (int64_t *)py_grid_points.data();
num_grid_points = (int64_t)py_grid_points.shape(0);
relative_grid_address = (int64_t(*)[3])py_relative_grid_address.data();
relative_grid_address = (int64_t (*)[3])py_relative_grid_address.data();
num_relative_grid_address = (int64_t)py_relative_grid_address.shape(0);
D_diag = (int64_t *)py_D_diag.data();
bz_grid_address = (int64_t(*)[3])py_bz_grid_address.data();
bz_grid_address = (int64_t (*)[3])py_bz_grid_address.data();
bz_map = (int64_t *)py_bz_map.data();
ph3py_get_neighboring_gird_points(
@ -743,10 +753,10 @@ void py_get_thm_integration_weights_at_grid_points(
double *iw;
double *frequency_points;
int64_t num_frequency_points, num_band, num_gp;
int64_t(*relative_grid_address)[4][3];
int64_t (*relative_grid_address)[4][3];
int64_t *D_diag;
int64_t *grid_points;
int64_t(*bz_grid_address)[3];
int64_t (*bz_grid_address)[3];
int64_t *bz_map;
int64_t *gp2irgp_map;
double *frequencies;
@ -754,11 +764,11 @@ void py_get_thm_integration_weights_at_grid_points(
iw = (double *)py_iw.data();
frequency_points = (double *)py_frequency_points.data();
num_frequency_points = (int64_t)py_frequency_points.shape(0);
relative_grid_address = (int64_t(*)[4][3])py_relative_grid_address.data();
relative_grid_address = (int64_t (*)[4][3])py_relative_grid_address.data();
D_diag = (int64_t *)py_D_diag.data();
grid_points = (int64_t *)py_grid_points.data();
num_gp = (int64_t)py_grid_points.shape(0);
bz_grid_address = (int64_t(*)[3])py_bz_grid_address.data();
bz_grid_address = (int64_t (*)[3])py_bz_grid_address.data();
bz_map = (int64_t *)py_bz_map.data();
gp2irgp_map = (int64_t *)py_gp2irgp_map.data();
frequencies = (double *)py_frequencies.data();
@ -777,14 +787,14 @@ int64_t py_tpl_get_triplets_reciprocal_mesh_at_q(
int64_t *map_triplets;
int64_t *map_q;
int64_t *D_diag;
int64_t(*rot)[3][3];
int64_t (*rot)[3][3];
int64_t num_rot;
int64_t num_ir;
map_triplets = (int64_t *)py_map_triplets.data();
map_q = (int64_t *)py_map_q.data();
D_diag = (int64_t *)py_D_diag.data();
rot = (int64_t(*)[3][3])py_rotations.data();
rot = (int64_t (*)[3][3])py_rotations.data();
num_rot = (int64_t)py_rotations.shape(0);
num_ir = ph3py_get_triplets_reciprocal_mesh_at_q(
@ -794,33 +804,33 @@ int64_t py_tpl_get_triplets_reciprocal_mesh_at_q(
return num_ir;
}
int64_t py_tpl_get_BZ_triplets_at_q(nb::ndarray<> py_triplets,
int64_t 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,
int64_t bz_grid_type) {
int64_t(*triplets)[3];
int64_t(*bz_grid_address)[3];
int64_t py_tpl_get_BZ_triplets_at_q(
nb::ndarray<> py_triplets, int64_t 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,
nb::ndarray<> py_reciprocal_lattice, int64_t bz_grid_type) {
int64_t (*triplets)[3];
int64_t (*bz_grid_address)[3];
int64_t *bz_map;
int64_t *map_triplets;
int64_t num_map_triplets;
int64_t *D_diag;
int64_t(*Q)[3];
int64_t (*Q)[3];
double (*reciprocal_lattice)[3];
int64_t num_ir;
triplets = (int64_t(*)[3])py_triplets.data();
bz_grid_address = (int64_t(*)[3])py_bz_grid_address.data();
triplets = (int64_t (*)[3])py_triplets.data();
bz_grid_address = (int64_t (*)[3])py_bz_grid_address.data();
bz_map = (int64_t *)py_bz_map.data();
map_triplets = (int64_t *)py_map_triplets.data();
num_map_triplets = (int64_t)py_map_triplets.shape(0);
D_diag = (int64_t *)py_D_diag.data();
Q = (int64_t(*)[3])py_Q.data();
Q = (int64_t (*)[3])py_Q.data();
reciprocal_lattice = (double (*)[3])py_reciprocal_lattice.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);
num_ir = ph3py_get_BZ_triplets_at_q(
triplets, grid_point, bz_grid_address, bz_map, map_triplets,
num_map_triplets, D_diag, Q, reciprocal_lattice, bz_grid_type);
return num_ir;
}
@ -835,10 +845,10 @@ void py_get_triplets_integration_weights(
double *iw;
char *iw_zero;
double *frequency_points;
int64_t(*relative_grid_address)[4][3];
int64_t (*relative_grid_address)[4][3];
int64_t *D_diag;
int64_t(*triplets)[3];
int64_t(*bz_grid_addresses)[3];
int64_t (*triplets)[3];
int64_t (*bz_grid_addresses)[3];
int64_t *bz_map;
double *frequencies1, *frequencies2;
int64_t num_band0, num_band1, num_band2, num_triplets;
@ -847,11 +857,11 @@ void py_get_triplets_integration_weights(
iw_zero = (char *)py_iw_zero.data();
frequency_points = (double *)py_frequency_points.data();
num_band0 = (int64_t)py_frequency_points.shape(0);
relative_grid_address = (int64_t(*)[4][3])py_relative_grid_address.data();
relative_grid_address = (int64_t (*)[4][3])py_relative_grid_address.data();
D_diag = (int64_t *)py_D_diag.data();
triplets = (int64_t(*)[3])py_triplets.data();
triplets = (int64_t (*)[3])py_triplets.data();
num_triplets = (int64_t)py_triplets.shape(0);
bz_grid_addresses = (int64_t(*)[3])py_bz_grid_addresses.data();
bz_grid_addresses = (int64_t (*)[3])py_bz_grid_addresses.data();
bz_map = (int64_t *)py_bz_map.data();
frequencies1 = (double *)py_frequencies1.data();
frequencies2 = (double *)py_frequencies2.data();
@ -871,7 +881,7 @@ void py_get_triplets_integration_weights_with_sigma(
double *iw;
char *iw_zero;
double *frequency_points;
int64_t(*triplets)[3];
int64_t (*triplets)[3];
double *frequencies;
int64_t num_band0, num_band, num_iw, num_triplets;
@ -879,7 +889,7 @@ void py_get_triplets_integration_weights_with_sigma(
iw_zero = (char *)py_iw_zero.data();
frequency_points = (double *)py_frequency_points.data();
num_band0 = (int64_t)py_frequency_points.shape(0);
triplets = (int64_t(*)[3])py_triplets.data();
triplets = (int64_t (*)[3])py_triplets.data();
num_triplets = (int64_t)py_triplets.shape(0);
frequencies = (double *)py_frequencies.data();
num_band = (int64_t)py_frequencies.shape(1);

View File

@ -49,7 +49,7 @@ static void get_collision_matrix(
const int64_t num_gp, const int64_t *map_q, const int64_t *rot_grid_points,
const int64_t num_ir_gp, const int64_t num_rot,
const double *rotations_cartesian, const double *g,
const double temperature, const double unit_conversion_factor,
const double temperature_THz, const double unit_conversion_factor,
const double cutoff_frequency);
static void get_collision_matrix_at_gp(
double *collision_matrix, const double *fc3_normal_squared,
@ -58,25 +58,25 @@ static void get_collision_matrix_at_gp(
const int64_t *map_q, const int64_t *rot_grid_points,
const int64_t num_ir_gp, const int64_t num_rot,
const double *rotations_cartesian, const double *g,
const double temperature, const double unit_conversion_factor,
const double temperature_THz, const double unit_conversion_factor,
const double cutoff_frequency, const int64_t *gp2tp_map, const int64_t i);
static void get_reducible_collision_matrix(
double *collision_matrix, const double *fc3_normal_squared,
const int64_t num_band0, const int64_t num_band, const double *frequencies,
const int64_t (*triplets)[3], const int64_t *triplets_map,
const int64_t num_gp, const int64_t *map_q, const double *g,
const double temperature, const double unit_conversion_factor,
const double temperature_THz, const double unit_conversion_factor,
const double cutoff_frequency);
static void get_reducible_collision_matrix_at_gp(
double *collision_matrix, const double *fc3_normal_squared,
const int64_t num_band0, const int64_t num_band, const double *frequencies,
const int64_t (*triplets)[3], const int64_t *triplets_map,
const int64_t num_gp, const int64_t *map_q, const double *g,
const double temperature, const double unit_conversion_factor,
const double temperature_THz, const double unit_conversion_factor,
const double cutoff_frequency, const int64_t *gp2tp_map, const int64_t i);
static int64_t get_inv_sinh(double *inv_sinh, const int64_t gp,
const double temperature, const double *frequencies,
const int64_t triplet[3],
const double temperature_THz,
const double *frequencies, const int64_t triplet[3],
const int64_t *triplets_map, const int64_t *map_q,
const int64_t num_band,
const double cutoff_frequency);
@ -89,7 +89,7 @@ void col_get_collision_matrix(
const int64_t *triplets_map, const int64_t *map_q,
const int64_t *rot_grid_points, const double *rotations_cartesian,
const double *g, const int64_t num_ir_gp, const int64_t num_gp,
const int64_t num_rot, const double temperature,
const int64_t num_rot, const double temperature_THz,
const double unit_conversion_factor, const double cutoff_frequency) {
int64_t num_triplets, num_band0, num_band;
@ -97,19 +97,19 @@ void col_get_collision_matrix(
num_band0 = fc3_normal_squared->dims[1];
num_band = fc3_normal_squared->dims[2];
get_collision_matrix(collision_matrix, fc3_normal_squared->data, num_band0,
num_band, frequencies, triplets, triplets_map, num_gp,
map_q, rot_grid_points, num_ir_gp, num_rot,
rotations_cartesian,
g + 2 * num_triplets * num_band0 * num_band * num_band,
temperature, unit_conversion_factor, cutoff_frequency);
get_collision_matrix(
collision_matrix, fc3_normal_squared->data, num_band0, num_band,
frequencies, triplets, triplets_map, num_gp, map_q, rot_grid_points,
num_ir_gp, num_rot, rotations_cartesian,
g + 2 * num_triplets * num_band0 * num_band * num_band, temperature_THz,
unit_conversion_factor, cutoff_frequency);
}
void col_get_reducible_collision_matrix(
double *collision_matrix, const Darray *fc3_normal_squared,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplets_map, const int64_t *map_q, const double *g,
const int64_t num_gp, const double temperature,
const int64_t num_gp, const double temperature_THz,
const double unit_conversion_factor, const double cutoff_frequency) {
int64_t num_triplets, num_band, num_band0;
@ -120,7 +120,7 @@ void col_get_reducible_collision_matrix(
get_reducible_collision_matrix(
collision_matrix, fc3_normal_squared->data, num_band0, num_band,
frequencies, triplets, triplets_map, num_gp, map_q,
g + 2 * num_triplets * num_band0 * num_band * num_band, temperature,
g + 2 * num_triplets * num_band0 * num_band * num_band, temperature_THz,
unit_conversion_factor, cutoff_frequency);
}
@ -131,7 +131,7 @@ static void get_collision_matrix(
const int64_t num_gp, const int64_t *map_q, const int64_t *rot_grid_points,
const int64_t num_ir_gp, const int64_t num_rot,
const double *rotations_cartesian, const double *g,
const double temperature, const double unit_conversion_factor,
const double temperature_THz, const double unit_conversion_factor,
const double cutoff_frequency) {
int64_t i;
int64_t *gp2tp_map;
@ -145,7 +145,7 @@ static void get_collision_matrix(
get_collision_matrix_at_gp(
collision_matrix, fc3_normal_squared, num_band0, num_band,
frequencies, triplets, triplets_map, map_q, rot_grid_points,
num_ir_gp, num_rot, rotations_cartesian, g, temperature,
num_ir_gp, num_rot, rotations_cartesian, g, temperature_THz,
unit_conversion_factor, cutoff_frequency, gp2tp_map, i);
}
@ -160,7 +160,7 @@ static void get_collision_matrix_at_gp(
const int64_t *map_q, const int64_t *rot_grid_points,
const int64_t num_ir_gp, const int64_t num_rot,
const double *rotations_cartesian, const double *g,
const double temperature, const double unit_conversion_factor,
const double temperature_THz, const double unit_conversion_factor,
const double cutoff_frequency, const int64_t *gp2tp_map, const int64_t i) {
int64_t j, k, l, m, n, ti, r_gp, swapped;
@ -171,9 +171,9 @@ static void get_collision_matrix_at_gp(
for (j = 0; j < num_rot; j++) {
r_gp = rot_grid_points[i * num_rot + j];
ti = gp2tp_map[triplets_map[r_gp]];
swapped =
get_inv_sinh(inv_sinh, r_gp, temperature, frequencies, triplets[ti],
triplets_map, map_q, num_band, cutoff_frequency);
swapped = get_inv_sinh(inv_sinh, r_gp, temperature_THz, frequencies,
triplets[ti], triplets_map, map_q, num_band,
cutoff_frequency);
for (k = 0; k < num_band0; k++) {
for (l = 0; l < num_band; l++) {
@ -219,7 +219,7 @@ static void get_reducible_collision_matrix(
const int64_t num_band0, const int64_t num_band, const double *frequencies,
const int64_t (*triplets)[3], const int64_t *triplets_map,
const int64_t num_gp, const int64_t *map_q, const double *g,
const double temperature, const double unit_conversion_factor,
const double temperature_THz, const double unit_conversion_factor,
const double cutoff_frequency) {
int64_t i;
int64_t *gp2tp_map;
@ -232,8 +232,9 @@ static void get_reducible_collision_matrix(
for (i = 0; i < num_gp; i++) {
get_reducible_collision_matrix_at_gp(
collision_matrix, fc3_normal_squared, num_band0, num_band,
frequencies, triplets, triplets_map, num_gp, map_q, g, temperature,
unit_conversion_factor, cutoff_frequency, gp2tp_map, i);
frequencies, triplets, triplets_map, num_gp, map_q, g,
temperature_THz, unit_conversion_factor, cutoff_frequency,
gp2tp_map, i);
}
free(gp2tp_map);
@ -245,7 +246,7 @@ static void get_reducible_collision_matrix_at_gp(
const int64_t num_band0, const int64_t num_band, const double *frequencies,
const int64_t (*triplets)[3], const int64_t *triplets_map,
const int64_t num_gp, const int64_t *map_q, const double *g,
const double temperature, const double unit_conversion_factor,
const double temperature_THz, const double unit_conversion_factor,
const double cutoff_frequency, const int64_t *gp2tp_map, const int64_t i) {
int64_t j, k, l, ti, swapped;
double collision;
@ -253,8 +254,9 @@ static void get_reducible_collision_matrix_at_gp(
inv_sinh = (double *)malloc(sizeof(double) * num_band);
ti = gp2tp_map[triplets_map[i]];
swapped = get_inv_sinh(inv_sinh, i, temperature, frequencies, triplets[ti],
triplets_map, map_q, num_band, cutoff_frequency);
swapped =
get_inv_sinh(inv_sinh, i, temperature_THz, frequencies, triplets[ti],
triplets_map, map_q, num_band, cutoff_frequency);
for (j = 0; j < num_band0; j++) {
for (k = 0; k < num_band; k++) {
@ -288,8 +290,8 @@ static void get_reducible_collision_matrix_at_gp(
}
static int64_t get_inv_sinh(double *inv_sinh, const int64_t gp,
const double temperature, const double *frequencies,
const int64_t triplet[3],
const double temperature_THz,
const double *frequencies, const int64_t triplet[3],
const int64_t *triplets_map, const int64_t *map_q,
const int64_t num_band,
const double cutoff_frequency) {
@ -310,7 +312,7 @@ static int64_t get_inv_sinh(double *inv_sinh, const int64_t gp,
for (i = 0; i < num_band; i++) {
f = frequencies[gp2 * num_band + i];
if (f > cutoff_frequency) {
inv_sinh[i] = funcs_inv_sinh_occupation(f, temperature);
inv_sinh[i] = funcs_inv_sinh_occupation(f, temperature_THz);
} else {
inv_sinh[i] = 0;
}

View File

@ -45,13 +45,13 @@ void col_get_collision_matrix(
const int64_t *triplets_map, const int64_t *map_q,
const int64_t *rot_grid_points, const double *rotations_cartesian,
const double *g, const int64_t num_ir_gp, const int64_t num_gp,
const int64_t num_rot, const double temperature,
const int64_t num_rot, const double temperature_THz,
const double unit_conversion_factor, const double cutoff_frequency);
void col_get_reducible_collision_matrix(
double *collision_matrix, const Darray *fc3_normal_squared,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplets_map, const int64_t *map_q, const double *g,
const int64_t num_gp, const double temperature,
const int64_t num_gp, const double temperature_THz,
const double unit_conversion_factor, const double cutoff_frequency);
#endif

View File

@ -38,17 +38,16 @@
#include "phonoc_const.h"
#define THZTOEVPARKB 47.992398658977166
#define INVSQRT2PI 0.3989422804014327
double funcs_bose_einstein(const double x, const double t) {
return 1.0 / (exp(THZTOEVPARKB * x / t) - 1);
double funcs_bose_einstein(const double x, const double temperature_THz) {
return 1.0 / (exp(x / temperature_THz) - 1);
}
double funcs_gaussian(const double x, const double sigma) {
return INVSQRT2PI / sigma * exp(-x * x / 2 / sigma / sigma);
}
double funcs_inv_sinh_occupation(const double x, const double t) {
return 1.0 / sinh(x * THZTOEVPARKB / 2 / t);
double funcs_inv_sinh_occupation(const double x, const double temperature_THz) {
return 1.0 / sinh(x / 2 / temperature_THz);
}

View File

@ -162,7 +162,7 @@ void grg_get_double_grid_address(int64_t address_double[3],
/* -------------------------------------------------------*/
/* Get address in single grid from address in double grid */
/* -------------------------------------------------------*/
/* This function shifts double-grid adress by PS and divides it by 2. */
/* This function shifts double-grid address by PS and divides it by 2. */
/* No modulo operation is applied to returned single-grid address. */
/* address : Single grid address. */
/* address_double : Double grid address. */

View File

@ -138,7 +138,7 @@ int64_t gridsys_get_bz_grid_addresses(
if (!niggli_reduce(niggli_lattice, GRIDSYS_NIGGLI_TOLERANCE)) {
return 0;
}
if (!lagmat_inverse_matrix_d3(inv_Lr, (double(*)[3])niggli_lattice,
if (!lagmat_inverse_matrix_d3(inv_Lr, (double (*)[3])niggli_lattice,
GRIDSYS_NIGGLI_TOLERANCE)) {
return 0;
}
@ -156,7 +156,7 @@ int64_t gridsys_get_bz_grid_addresses(
bzgrid->bzg2grg = bzg2grg;
bzgrid->type = bz_grid_type;
lagmat_multiply_matrix_l3(bzgrid->Q, inv_Mpr_int, Q);
lagmat_copy_matrix_d3(bzgrid->reclat, (double(*)[3])niggli_lattice);
lagmat_copy_matrix_d3(bzgrid->reclat, (double (*)[3])niggli_lattice);
for (i = 0; i < 3; i++) {
bzgrid->D_diag[i] = D_diag[i];
bzgrid->PS[i] = PS[i];
@ -220,7 +220,7 @@ int64_t gridsys_get_bz_triplets_at_q(
const int64_t (*bz_grid_addresses)[3], const int64_t *bz_map,
const int64_t *map_triplets, const int64_t num_map_triplets,
const int64_t D_diag[3], const int64_t Q[3][3],
const int64_t bz_grid_type) {
const double reciprocal_lattice[3][3], const int64_t bz_grid_type) {
RecgridConstBZGrid *bzgrid;
int64_t i, j, num_ir;
@ -237,6 +237,7 @@ int64_t gridsys_get_bz_triplets_at_q(
bzgrid->D_diag[i] = D_diag[i];
bzgrid->PS[i] = 0;
for (j = 0; j < 3; j++) {
bzgrid->reclat[i][j] = reciprocal_lattice[i][j];
bzgrid->Q[i][j] = Q[i][j];
}
}
@ -266,7 +267,7 @@ int64_t gridsys_get_thm_relative_grid_address(
return thm_get_relative_grid_address(relative_grid_addresses, rec_lattice);
}
/* relative_grid_addresses are given as P multipled with those from */
/* relative_grid_addresses are given as P multiplied with those from */
/* dataset, i.e., */
/* np.dot(relative_grid_addresses, P.T) */
int64_t gridsys_get_integration_weight(

View File

@ -140,7 +140,7 @@ int64_t gridsys_get_reciprocal_point_group(int64_t rec_rotations[48][3][3],
/**
* @brief Return D, P, Q of Smith normal form of A.
*
* @param D_diag Diagonal elements of diagnoal matrix D
* @param D_diag Diagonal elements of diagonal matrix D
* @param P Unimodular matrix P
* @param Q Unimodular matrix Q
* @param A Integer matrix
@ -157,7 +157,7 @@ int64_t gridsys_get_snf3x3(int64_t D_diag[3], int64_t P[3][3], int64_t Q[3][3],
* {tilde-R^T}
* @param rotations Original rotations matrices in reciprocal space {R^T}
* @param num_rot Number of rotation matrices
* @param D_diag Diagonal elements of diagnoal matrix D of Smith normal form
* @param D_diag Diagonal elements of diagonal matrix D of Smith normal form
* @param Q Unimodular matrix Q of Smith normal form
* @return int64_t
*/
@ -174,7 +174,7 @@ int64_t gridsys_transform_rotations(int64_t (*transformed_rots)[3][3],
* array size of prod(D_diag)
* @param rotations Transformed rotation matrices in reciprocal space
* @param num_rot Number of rotation matrices
* @param D_diag Diagonal elements of diagnoal matrix D of Smith normal form
* @param D_diag Diagonal elements of diagonal matrix D of Smith normal form
* @param PS Shift in GR-grid
*/
void gridsys_get_ir_grid_map(int64_t *ir_grid_map,
@ -193,7 +193,7 @@ void gridsys_get_ir_grid_map(int64_t *ir_grid_map,
* @param bzg2grg Mapping table of bz_grid_addresses to gr_grid_addresses. In
* type-II, len(bzg2grg) == len(bz_grid_addresses) <= (D_diag[0] + 1) *
* (D_diag[1] + 1) * (D_diag[2] + 1).
* @param D_diag Diagonal elements of diagnoal matrix D of Smith normal form
* @param D_diag Diagonal elements of diagonal matrix D of Smith normal form
* @param Q Unimodular matrix Q of Smith normal form
* @param PS Shift in GR-grid
* @param rec_lattice Reduced reciprocal basis vectors in column vectors
@ -211,7 +211,7 @@ int64_t gridsys_get_bz_grid_addresses(
*
* @param bz_grid_index BZ grid point index
* @param rotation Transformed rotation in reciprocal space tilde-R^T
* @param bz_grid_addresses BZ grid point adddresses
* @param bz_grid_addresses BZ grid point addresses
* @param bz_map List of accumulated numbers of BZ grid points from the
* first GR grid point to the last grid point. In type-II, [0, 1, 3, 4, ...]
* means multiplicities of [1, 2, 1, ...], with len(bz_map)=product(D_diag) + 1.
@ -234,7 +234,7 @@ int64_t gridsys_rotate_bz_grid_index(
* @param map_q Mapping table from all grid points to grid point indices of
* irreducible q-points under the stabilizer subgroup of q
* @param grid_index Grid point index of q in GR-grid
* @param D_diag Diagonal elements of diagnoal matrix D of Smith normal form
* @param D_diag Diagonal elements of diagonal matrix D of Smith normal form
* @param is_time_reversal With (1) or without (0) time reversal symmetry
* @param num_rot Number of rotation matrices
* @param rec_rotations Transformed rotation matrices in reciprocal space
@ -262,7 +262,7 @@ int64_t gridsys_get_triplets_at_q(int64_t *map_triplets, int64_t *map_q,
* @param map_triplets Mapping table from all grid points to grid points of
* independent q'
* @param num_map_triplets First dimension of map_triplets
* @param D_diag Diagonal elements of diagnoal matrix D of Smith normal form
* @param D_diag Diagonal elements of diagonal matrix D of Smith normal form
* @param Q Unimodular matrix Q of Smith normal form
* @param bz_grid_type Data structure type I (old and sparse) or II (new and
* dense, recommended) of bz_map
@ -272,7 +272,8 @@ int64_t gridsys_get_bz_triplets_at_q(
int64_t (*ir_triplets)[3], const int64_t bz_grid_index,
const int64_t (*bz_grid_addresses)[3], const int64_t *bz_map,
const int64_t *map_triplets, const int64_t num_map_triplets,
const int64_t D_diag[3], const int64_t Q[3][3], const int64_t bz_grid_type);
const int64_t D_diag[3], const int64_t Q[3][3],
const double reciprocal_lattice[3][3], const int64_t bz_grid_type);
/**
* @brief Return integration weight of linear tetrahedron method

View File

@ -53,7 +53,7 @@ static void detailed_imag_self_energy_at_triplet(
const int64_t num_band0, const int64_t num_band,
const double *fc3_normal_squared, const double *frequencies,
const int64_t triplet[3], const double *g1, const double *g2_3,
const char *g_zero, const double *temperatures, const int64_t num_temps,
const char *g_zero, const double *temperatures_THz, const int64_t num_temps,
const double cutoff_frequency);
static double collect_detailed_imag_self_energy(
double *imag_self_energy, const int64_t num_band,
@ -72,11 +72,11 @@ void ise_get_imag_self_energy_with_g(
double *imag_self_energy, const Darray *fc3_normal_squared,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplet_weights, const double *g, const char *g_zero,
const double temperature, const double cutoff_frequency,
const double temperature_THz, const double cutoff_frequency,
const int64_t num_frequency_points, const int64_t frequency_point_index) {
int64_t i, j, num_triplets, num_band0, num_band, num_band_prod;
int64_t num_g_pos, g_index_dims, g_index_shift;
int64_t(*g_pos)[4];
int64_t (*g_pos)[4];
double *ise;
int64_t at_a_frequency_point;
@ -115,10 +115,10 @@ void ise_get_imag_self_energy_with_g(
/**
* g_pos contains the indices of g that are known non-zeros in series.
*
* ise_set_g_pos works for frquency points as bands.
* ise_set_g_pos works for frequency points as bands.
* set_g_pos_frequency_point works for frequency sampling mode.
*/
g_pos = (int64_t(*)[4])malloc(sizeof(int64_t[4]) * num_band_prod);
g_pos = (int64_t (*)[4])malloc(sizeof(int64_t[4]) * num_band_prod);
if (at_a_frequency_point) {
num_g_pos = set_g_pos_frequency_point(
g_pos, num_band0, num_band,
@ -134,7 +134,7 @@ void ise_get_imag_self_energy_with_g(
triplets[i], triplet_weights[i],
g + i * g_index_dims + g_index_shift,
g + (i + num_triplets) * g_index_dims + g_index_shift, g_pos,
num_g_pos, &temperature, 1, cutoff_frequency, 0,
num_g_pos, &temperature_THz, 1, cutoff_frequency, 0,
at_a_frequency_point);
free(g_pos);
@ -160,7 +160,7 @@ void ise_get_detailed_imag_self_energy_with_g(
double *imag_self_energy_U, const Darray *fc3_normal_squared,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplet_weights, const int64_t (*bz_grid_addresses)[3],
const double *g, const char *g_zero, const double temperature,
const double *g, const char *g_zero, const double temperature_THz,
const double cutoff_frequency) {
double *ise;
int64_t i, j, num_triplets, num_band0, num_band, num_band_prod;
@ -187,7 +187,7 @@ void ise_get_detailed_imag_self_energy_with_g(
num_band0, num_band, fc3_normal_squared->data + i * num_band_prod,
frequencies, triplets[i], g + i * num_band_prod,
g + (i + num_triplets) * num_band_prod, g_zero + i * num_band_prod,
&temperature, 1, cutoff_frequency);
&temperature_THz, 1, cutoff_frequency);
}
is_N = (int64_t *)malloc(sizeof(int64_t) * num_triplets);
@ -224,7 +224,7 @@ void ise_imag_self_energy_at_triplet(
const double *fc3_normal_squared, const double *frequencies,
const int64_t triplet[3], const int64_t triplet_weight, const double *g1,
const double *g2_3, const int64_t (*g_pos)[4], const int64_t num_g_pos,
const double *temperatures, const int64_t num_temps,
const double *temperatures_THz, const int64_t num_temps,
const double cutoff_frequency, const int64_t openmp_per_triplets,
const int64_t at_a_frequency_point) {
int64_t i, j;
@ -237,7 +237,7 @@ void ise_imag_self_energy_at_triplet(
for (i = 0; i < num_temps; i++) {
set_occupations(n1 + i * num_band, n2 + i * num_band, num_band,
temperatures[i], triplet, frequencies,
temperatures_THz[i], triplet, frequencies,
cutoff_frequency);
}
@ -259,7 +259,7 @@ void ise_imag_self_energy_at_triplet(
n2[j * num_band + g_pos[i][2]] < 0) {
ise_at_g_pos[i * num_temps + j] = 0;
} else {
if (temperatures[j] > 0) {
if (temperatures_THz[j] > 0) {
ise_at_g_pos[i * num_temps + j] =
((n1[j * num_band + g_pos[i][1]] +
n2[j * num_band + g_pos[i][2]] + 1) *
@ -359,7 +359,7 @@ static void detailed_imag_self_energy_at_triplet(
const int64_t num_band0, const int64_t num_band,
const double *fc3_normal_squared, const double *frequencies,
const int64_t triplet[3], const double *g1, const double *g2_3,
const char *g_zero, const double *temperatures, const int64_t num_temps,
const char *g_zero, const double *temperatures_THz, const int64_t num_temps,
const double cutoff_frequency) {
int64_t i, j, adrs_shift;
double *n1, *n2;
@ -371,12 +371,12 @@ static void detailed_imag_self_energy_at_triplet(
n2 = (double *)malloc(sizeof(double) * num_band);
for (i = 0; i < num_temps; i++) {
set_occupations(n1, n2, num_band, temperatures[i], triplet, frequencies,
cutoff_frequency);
set_occupations(n1, n2, num_band, temperatures_THz[i], triplet,
frequencies, cutoff_frequency);
for (j = 0; j < num_band0; j++) {
adrs_shift = j * num_band * num_band;
if (temperatures[i] > 0) {
if (temperatures_THz[i] > 0) {
imag_self_energy[i * num_band0 + j] =
collect_detailed_imag_self_energy(
detailed_imag_self_energy + adrs_shift, num_band,
@ -452,8 +452,8 @@ static double collect_detailed_imag_self_energy_0K(
}
static void set_occupations(double *n1, double *n2, const int64_t num_band,
const double temperature, const int64_t triplet[3],
const double *frequencies,
const double temperature_THz,
const int64_t triplet[3], const double *frequencies,
const double cutoff_frequency) {
int64_t j;
double f1, f2;
@ -462,12 +462,12 @@ static void set_occupations(double *n1, double *n2, const int64_t num_band,
f1 = frequencies[triplet[1] * num_band + j];
f2 = frequencies[triplet[2] * num_band + j];
if (f1 > cutoff_frequency) {
n1[j] = funcs_bose_einstein(f1, temperature);
n1[j] = funcs_bose_einstein(f1, temperature_THz);
} else {
n1[j] = -1;
}
if (f2 > cutoff_frequency) {
n2[j] = funcs_bose_einstein(f2, temperature);
n2[j] = funcs_bose_einstein(f2, temperature_THz);
} else {
n2[j] = -1;
}

View File

@ -44,21 +44,21 @@ void ise_get_imag_self_energy_with_g(
double *imag_self_energy, const Darray *fc3_normal_squared,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplet_weights, const double *g, const char *g_zero,
const double temperature, const double cutoff_frequency,
const double temperature_THz, const double cutoff_frequency,
const int64_t num_frequency_points, const int64_t frequency_point_index);
void ise_get_detailed_imag_self_energy_with_g(
double *detailed_imag_self_energy, double *imag_self_energy_N,
double *imag_self_energy_U, const Darray *fc3_normal_squared,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplet_weights, const int64_t (*bz_grid_addresses)[3],
const double *g, const char *g_zero, const double temperature,
const double *g, const char *g_zero, const double temperature_THz,
const double cutoff_frequency);
void ise_imag_self_energy_at_triplet(
double *imag_self_energy, const int64_t num_band0, const int64_t num_band,
const double *fc3_normal_squared, const double *frequencies,
const int64_t triplet[3], const int64_t triplet_weight, const double *g1,
const double *g2_3, const int64_t (*g_pos)[4], const int64_t num_g_pos,
const double *temperatures, const int64_t num_temps,
const double *temperatures_THz, const int64_t num_temps,
const double cutoff_frequency, const int64_t openmp_possible,
const int64_t at_a_frequency_point);
int64_t ise_set_g_pos(int64_t (*g_pos)[4], const int64_t num_band0,

View File

@ -56,9 +56,10 @@ static void real_to_normal(
const lapack_complex_double *eigvecs2, const double *fc3,
const int64_t is_compact_fc3, const double q_vecs[3][3], /* q0, q1, q2 */
const AtomTriplets *atom_triplets, const double *masses,
const int64_t *band_indices, const int64_t num_band,
const double cutoff_frequency, const int64_t triplet_index,
const int64_t num_triplets, const int64_t openmp_per_triplets);
const int64_t *band_indices, const int64_t num_band0,
const int64_t num_band, const double cutoff_frequency,
const int64_t triplet_index, const int64_t num_triplets,
const int64_t openmp_per_triplets);
static void real_to_normal_sym_q(
double *fc3_normal_squared, const int64_t (*g_pos)[4],
const int64_t num_g_pos, double *const freqs[3],
@ -79,7 +80,7 @@ void itr_get_interaction(
const AtomTriplets *atom_triplets, const double *masses,
const int64_t *band_indices, const int64_t symmetrize_fc3_q,
const double cutoff_frequency, const int64_t openmp_per_triplets) {
int64_t(*g_pos)[4];
int64_t (*g_pos)[4];
int64_t i;
int64_t num_band, num_band0, num_band_prod, num_g_pos;
@ -90,11 +91,11 @@ void itr_get_interaction(
num_band_prod = num_band0 * num_band * num_band;
#ifdef _OPENMP
#pragma omp parallel for schedule(guided) private( \
num_g_pos, g_pos) if (openmp_per_triplets)
#pragma omp parallel for schedule(guided) \
private(num_g_pos, g_pos) if (openmp_per_triplets)
#endif
for (i = 0; i < num_triplets; i++) {
g_pos = (int64_t(*)[4])malloc(sizeof(int64_t[4]) * num_band_prod);
g_pos = (int64_t (*)[4])malloc(sizeof(int64_t[4]) * num_band_prod);
num_g_pos = ise_set_g_pos(g_pos, num_band0, num_band,
g_zero + i * num_band_prod);
@ -177,7 +178,7 @@ void itr_get_interaction_at_triplet(
eigenvectors + triplet[1] * num_band * num_band,
eigenvectors + triplet[2] * num_band * num_band, fc3,
is_compact_fc3, q_vecs, /* q0, q1, q2 */
atom_triplets, masses, band_indices, num_band,
atom_triplets, masses, band_indices, num_band0, num_band,
cutoff_frequency, triplet_index, num_triplets,
openmp_per_triplets);
}
@ -191,9 +192,10 @@ static void real_to_normal(
const lapack_complex_double *eigvecs2, const double *fc3,
const int64_t is_compact_fc3, const double q_vecs[3][3], /* q0, q1, q2 */
const AtomTriplets *atom_triplets, const double *masses,
const int64_t *band_indices, const int64_t num_band,
const double cutoff_frequency, const int64_t triplet_index,
const int64_t num_triplets, const int64_t openmp_per_triplets) {
const int64_t *band_indices, const int64_t num_band0,
const int64_t num_band, const double cutoff_frequency,
const int64_t triplet_index, const int64_t num_triplets,
const int64_t openmp_per_triplets) {
lapack_complex_double *fc3_reciprocal;
lapack_complex_double comp_zero;
int64_t i;
@ -215,8 +217,8 @@ static void real_to_normal(
#endif
reciprocal_to_normal_squared(
fc3_normal_squared, g_pos, num_g_pos, fc3_reciprocal, freqs0, freqs1,
freqs2, eigvecs0, eigvecs1, eigvecs2, masses, band_indices, num_band,
cutoff_frequency, openmp_per_triplets);
freqs2, eigvecs0, eigvecs1, eigvecs2, masses, band_indices, num_band0,
num_band, cutoff_frequency, openmp_per_triplets);
free(fc3_reciprocal);
fc3_reciprocal = NULL;
@ -256,8 +258,8 @@ static void real_to_normal_sym_q(
freqs[index_exchange[i][2]], eigvecs[index_exchange[i][0]],
eigvecs[index_exchange[i][1]], eigvecs[index_exchange[i][2]], fc3,
is_compact_fc3, q_vecs_ex, /* q0, q1, q2 */
atom_triplets, masses, band_indices, num_band, cutoff_frequency,
triplet_index, num_triplets, openmp_per_triplets);
atom_triplets, masses, band_indices, num_band0, num_band,
cutoff_frequency, triplet_index, num_triplets, openmp_per_triplets);
for (j = 0; j < num_band0; j++) {
for (k = 0; k < num_band; k++) {
for (l = 0; l < num_band; l++) {

View File

@ -63,12 +63,13 @@ int64_t ph3py_get_interaction(
const _lapack_complex_double *eigenvectors, const int64_t (*triplets)[3],
const int64_t num_triplets, const int64_t (*bz_grid_addresses)[3],
const int64_t D_diag[3], const int64_t Q[3][3], const double *fc3,
const int64_t is_compact_fc3, const double (*svecs)[3],
const int64_t multi_dims[2], const int64_t (*multiplicity)[2],
const double *masses, const int64_t *p2s_map, const int64_t *s2p_map,
const int64_t *band_indices, const int64_t symmetrize_fc3_q,
const int64_t make_r0_average, const char *all_shortest,
const double cutoff_frequency, const int64_t openmp_per_triplets) {
const char *fc3_nonzero_indices, const int64_t is_compact_fc3,
const double (*svecs)[3], const int64_t multi_dims[2],
const int64_t (*multiplicity)[2], const double *masses,
const int64_t *p2s_map, const int64_t *s2p_map, const int64_t *band_indices,
const int64_t symmetrize_fc3_q, const int64_t make_r0_average,
const char *all_shortest, const double cutoff_frequency,
const int64_t openmp_per_triplets) {
RecgridConstBZGrid *bzgrid;
AtomTriplets *atom_triplets;
int64_t i, j;
@ -102,6 +103,7 @@ int64_t ph3py_get_interaction(
atom_triplets->s2p_map = s2p_map;
atom_triplets->make_r0_average = make_r0_average;
atom_triplets->all_shortest = all_shortest;
atom_triplets->nonzero_indices = fc3_nonzero_indices;
itr_get_interaction(fc3_normal_squared, g_zero, frequencies,
(lapack_complex_double *)eigenvectors, triplets,
@ -127,13 +129,14 @@ int64_t ph3py_get_pp_collision(
const int64_t (*bz_grid_addresses)[3], /* thm */
const int64_t *bz_map, /* thm */
const int64_t bz_grid_type, const int64_t D_diag[3], const int64_t Q[3][3],
const double *fc3, const int64_t is_compact_fc3, const double (*svecs)[3],
const double *fc3, const char *fc3_nonzero_indices,
const int64_t is_compact_fc3, const double (*svecs)[3],
const int64_t multi_dims[2], const int64_t (*multiplicity)[2],
const double *masses, const int64_t *p2s_map, const int64_t *s2p_map,
const Larray *band_indices, const Darray *temperatures, const int64_t is_NU,
const int64_t symmetrize_fc3_q, const int64_t make_r0_average,
const char *all_shortest, const double cutoff_frequency,
const int64_t openmp_per_triplets) {
const Larray *band_indices, const Darray *temperatures_THz,
const int64_t is_NU, const int64_t symmetrize_fc3_q,
const int64_t make_r0_average, const char *all_shortest,
const double cutoff_frequency, const int64_t openmp_per_triplets) {
RecgridConstBZGrid *bzgrid;
AtomTriplets *atom_triplets;
int64_t i, j;
@ -169,12 +172,13 @@ int64_t ph3py_get_pp_collision(
atom_triplets->s2p_map = s2p_map;
atom_triplets->make_r0_average = make_r0_average;
atom_triplets->all_shortest = all_shortest;
atom_triplets->nonzero_indices = fc3_nonzero_indices;
ppc_get_pp_collision(imag_self_energy, relative_grid_address, frequencies,
(lapack_complex_double *)eigenvectors, triplets,
num_triplets, triplet_weights, bzgrid, fc3,
is_compact_fc3, atom_triplets, masses, band_indices,
temperatures, is_NU, symmetrize_fc3_q,
temperatures_THz, is_NU, symmetrize_fc3_q,
cutoff_frequency, openmp_per_triplets);
free(atom_triplets);
@ -192,10 +196,11 @@ int64_t ph3py_get_pp_collision_with_sigma(
const int64_t (*triplets)[3], const int64_t num_triplets,
const int64_t *triplet_weights, const int64_t (*bz_grid_addresses)[3],
const int64_t D_diag[3], const int64_t Q[3][3], const double *fc3,
const int64_t is_compact_fc3, const double (*svecs)[3],
const int64_t multi_dims[2], const int64_t (*multiplicity)[2],
const double *masses, const int64_t *p2s_map, const int64_t *s2p_map,
const Larray *band_indices, const Darray *temperatures, const int64_t is_NU,
const char *fc3_nonzero_indices, const int64_t is_compact_fc3,
const double (*svecs)[3], const int64_t multi_dims[2],
const int64_t (*multiplicity)[2], const double *masses,
const int64_t *p2s_map, const int64_t *s2p_map, const Larray *band_indices,
const Darray *temperatures_THz, const int64_t is_NU,
const int64_t symmetrize_fc3_q, const int64_t make_r0_average,
const char *all_shortest, const double cutoff_frequency,
const int64_t openmp_per_triplets) {
@ -232,13 +237,14 @@ int64_t ph3py_get_pp_collision_with_sigma(
atom_triplets->s2p_map = s2p_map;
atom_triplets->make_r0_average = make_r0_average;
atom_triplets->all_shortest = all_shortest;
atom_triplets->nonzero_indices = fc3_nonzero_indices;
ppc_get_pp_collision_with_sigma(
imag_self_energy, sigma, sigma_cutoff, frequencies,
(lapack_complex_double *)eigenvectors, triplets, num_triplets,
triplet_weights, bzgrid, fc3, is_compact_fc3, atom_triplets, masses,
band_indices, temperatures, is_NU, symmetrize_fc3_q, cutoff_frequency,
openmp_per_triplets);
band_indices, temperatures_THz, is_NU, symmetrize_fc3_q,
cutoff_frequency, openmp_per_triplets);
free(atom_triplets);
atom_triplets = NULL;
@ -253,11 +259,11 @@ void ph3py_get_imag_self_energy_at_bands_with_g(
double *imag_self_energy, const Darray *fc3_normal_squared,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplet_weights, const double *g, const char *g_zero,
const double temperature, const double cutoff_frequency,
const double temperature_THz, const double cutoff_frequency,
const int64_t num_frequency_points, const int64_t frequency_point_index) {
ise_get_imag_self_energy_with_g(
imag_self_energy, fc3_normal_squared, frequencies, triplets,
triplet_weights, g, g_zero, temperature, cutoff_frequency,
triplet_weights, g, g_zero, temperature_THz, cutoff_frequency,
num_frequency_points, frequency_point_index);
}
@ -266,23 +272,23 @@ void ph3py_get_detailed_imag_self_energy_at_bands_with_g(
double *imag_self_energy_U, const Darray *fc3_normal_squared,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplet_weights, const int64_t (*bz_grid_addresses)[3],
const double *g, const char *g_zero, const double temperature,
const double *g, const char *g_zero, const double temperature_THz,
const double cutoff_frequency) {
ise_get_detailed_imag_self_energy_with_g(
detailed_imag_self_energy, imag_self_energy_N, imag_self_energy_U,
fc3_normal_squared, frequencies, triplets, triplet_weights,
bz_grid_addresses, g, g_zero, temperature, cutoff_frequency);
bz_grid_addresses, g, g_zero, temperature_THz, cutoff_frequency);
}
void ph3py_get_real_self_energy_at_bands(
double *real_self_energy, const Darray *fc3_normal_squared,
const int64_t *band_indices, const double *frequencies,
const int64_t (*triplets)[3], const int64_t *triplet_weights,
const double epsilon, const double temperature,
const double epsilon, const double temperature_THz,
const double unit_conversion_factor, const double cutoff_frequency) {
rse_get_real_self_energy_at_bands(real_self_energy, fc3_normal_squared,
band_indices, frequencies, triplets,
triplet_weights, epsilon, temperature,
triplet_weights, epsilon, temperature_THz,
unit_conversion_factor, cutoff_frequency);
}
@ -291,11 +297,11 @@ void ph3py_get_real_self_energy_at_frequency_point(
const Darray *fc3_normal_squared, const int64_t *band_indices,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplet_weights, const double epsilon,
const double temperature, const double unit_conversion_factor,
const double temperature_THz, const double unit_conversion_factor,
const double cutoff_frequency) {
rse_get_real_self_energy_at_frequency_point(
real_self_energy, frequency_point, fc3_normal_squared, band_indices,
frequencies, triplets, triplet_weights, epsilon, temperature,
frequencies, triplets, triplet_weights, epsilon, temperature_THz,
unit_conversion_factor, cutoff_frequency);
}
@ -305,12 +311,12 @@ void ph3py_get_collision_matrix(
const int64_t *triplets_map, const int64_t *map_q,
const int64_t *rotated_grid_points, const double *rotations_cartesian,
const double *g, const int64_t num_ir_gp, const int64_t num_gp,
const int64_t num_rot, const double temperature,
const int64_t num_rot, const double temperature_THz,
const double unit_conversion_factor, const double cutoff_frequency) {
col_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,
temperature_THz, unit_conversion_factor,
cutoff_frequency);
}
@ -318,11 +324,11 @@ void ph3py_get_reducible_collision_matrix(
double *collision_matrix, const Darray *fc3_normal_squared,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplets_map, const int64_t *map_q, const double *g,
const int64_t num_gp, const double temperature,
const int64_t num_gp, const double temperature_THz,
const double unit_conversion_factor, const double cutoff_frequency) {
col_get_reducible_collision_matrix(
collision_matrix, fc3_normal_squared, frequencies, triplets,
triplets_map, map_q, g, num_gp, temperature, unit_conversion_factor,
triplets_map, map_q, g, num_gp, temperature_THz, unit_conversion_factor,
cutoff_frequency);
}
@ -405,7 +411,7 @@ int64_t ph3py_get_BZ_triplets_at_q(
const int64_t (*bz_grid_addresses)[3], const int64_t *bz_map,
const int64_t *map_triplets, const int64_t num_map_triplets,
const int64_t D_diag[3], const int64_t Q[3][3],
const int64_t bz_grid_type) {
const double reciprocal_lattice[3][3], const int64_t bz_grid_type) {
RecgridConstBZGrid *bzgrid;
int64_t i, j, num_ir;
@ -423,6 +429,7 @@ int64_t ph3py_get_BZ_triplets_at_q(
bzgrid->PS[i] = 0;
for (j = 0; j < 3; j++) {
bzgrid->Q[i][j] = Q[i][j];
bzgrid->reclat[i][j] = reciprocal_lattice[i][j];
}
}
bzgrid->size = num_map_triplets;
@ -435,7 +442,7 @@ int64_t ph3py_get_BZ_triplets_at_q(
return num_ir;
}
/* relative_grid_addresses are given as P multipled with those from dataset,
/* relative_grid_addresses are given as P multiplied with those from dataset,
* i.e.,
* np.dot(relative_grid_addresses, P.T) */
int64_t ph3py_get_integration_weight(
@ -601,7 +608,7 @@ void ph3py_get_relative_grid_address(int64_t relative_grid_address[24][4][3],
/* tpi_get_neighboring_grid_points around multiple grid points for using
* openmp
*
* relative_grid_addresses are given as P multipled with those from dataset,
* relative_grid_addresses are given as P multiplied with those from dataset,
* i.e.,
* np.dot(relative_grid_addresses, P.T) */
int64_t ph3py_get_neighboring_gird_points(
@ -644,7 +651,7 @@ int64_t ph3py_get_neighboring_gird_points(
/* thm_get_integration_weight at multiple grid points for using openmp
*
* relative_grid_addresses are given as P multipled with those from dataset,
* relative_grid_addresses are given as P multiplied with those from dataset,
* i.e.,
* np.dot(relative_grid_addresses, P.T) */
int64_t ph3py_get_thm_integration_weights_at_grid_points(

View File

@ -53,12 +53,13 @@ int64_t ph3py_get_interaction(
const _lapack_complex_double *eigenvectors, const int64_t (*triplets)[3],
const int64_t num_triplets, const int64_t (*bz_grid_addresses)[3],
const int64_t D_diag[3], const int64_t Q[3][3], const double *fc3,
const int64_t is_compact_fc3, const double (*svecs)[3],
const int64_t multi_dims[2], const int64_t (*multi)[2],
const double *masses, const int64_t *p2s_map, const int64_t *s2p_map,
const int64_t *band_indices, const int64_t symmetrize_fc3_q,
const int64_t make_r0_average, const char *all_shortest,
const double cutoff_frequency, const int64_t openmp_per_triplets);
const char *fc3_nonzero_indices, const int64_t is_compact_fc3,
const double (*svecs)[3], const int64_t multi_dims[2],
const int64_t (*multi)[2], const double *masses, const int64_t *p2s_map,
const int64_t *s2p_map, const int64_t *band_indices,
const int64_t symmetrize_fc3_q, const int64_t make_r0_average,
const char *all_shortest, const double cutoff_frequency,
const int64_t openmp_per_triplets);
int64_t ph3py_get_pp_collision(
double *imag_self_energy,
const int64_t relative_grid_address[24][4][3], /* thm */
@ -68,23 +69,25 @@ int64_t ph3py_get_pp_collision(
const int64_t (*bz_grid_addresses)[3], /* thm */
const int64_t *bz_map, /* thm */
const int64_t bz_grid_type, const int64_t D_diag[3], const int64_t Q[3][3],
const double *fc3, const int64_t is_compact_fc3, const double (*svecs)[3],
const double *fc3, const char *fc3_nonzero_indices,
const int64_t is_compact_fc3, const double (*svecs)[3],
const int64_t multi_dims[2], const int64_t (*multi)[2],
const double *masses, const int64_t *p2s_map, const int64_t *s2p_map,
const Larray *band_indices, const Darray *temperatures, const int64_t is_NU,
const int64_t symmetrize_fc3_q, const int64_t make_r0_average,
const char *all_shortest, const double cutoff_frequency,
const int64_t openmp_per_triplets);
const Larray *band_indices, const Darray *temperatures_THz,
const int64_t is_NU, const int64_t symmetrize_fc3_q,
const int64_t make_r0_average, const char *all_shortest,
const double cutoff_frequency, const int64_t openmp_per_triplets);
int64_t ph3py_get_pp_collision_with_sigma(
double *imag_self_energy, const double sigma, const double sigma_cutoff,
const double *frequencies, const _lapack_complex_double *eigenvectors,
const int64_t (*triplets)[3], const int64_t num_triplets,
const int64_t *triplet_weights, const int64_t (*bz_grid_addresses)[3],
const int64_t D_diag[3], const int64_t Q[3][3], const double *fc3,
const int64_t is_compact_fc3, const double (*svecs)[3],
const int64_t multi_dims[2], const int64_t (*multi)[2],
const double *masses, const int64_t *p2s_map, const int64_t *s2p_map,
const Larray *band_indices, const Darray *temperatures, const int64_t is_NU,
const char *fc3_nonzero_indices, const int64_t is_compact_fc3,
const double (*svecs)[3], const int64_t multi_dims[2],
const int64_t (*multi)[2], const double *masses, const int64_t *p2s_map,
const int64_t *s2p_map, const Larray *band_indices,
const Darray *temperatures_THz, const int64_t is_NU,
const int64_t symmetrize_fc3_q, const int64_t make_r0_average,
const char *all_shortest, const double cutoff_frequency,
const int64_t openmp_per_triplets);
@ -92,27 +95,27 @@ void ph3py_get_imag_self_energy_at_bands_with_g(
double *imag_self_energy, const Darray *fc3_normal_squared,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplet_weights, const double *g, const char *g_zero,
const double temperature, const double cutoff_frequency,
const double temperature_THz, const double cutoff_frequency,
const int64_t num_frequency_points, const int64_t frequency_point_index);
void ph3py_get_detailed_imag_self_energy_at_bands_with_g(
double *detailed_imag_self_energy, double *imag_self_energy_N,
double *imag_self_energy_U, const Darray *fc3_normal_squared,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplet_weights, const int64_t (*bz_grid_addresses)[3],
const double *g, const char *g_zero, const double temperature,
const double *g, const char *g_zero, const double temperature_THz,
const double cutoff_frequency);
void ph3py_get_real_self_energy_at_bands(
double *real_self_energy, const Darray *fc3_normal_squared,
const int64_t *band_indices, const double *frequencies,
const int64_t (*triplets)[3], const int64_t *triplet_weights,
const double epsilon, const double temperature,
const double epsilon, const double temperature_THz,
const double unit_conversion_factor, const double cutoff_frequency);
void ph3py_get_real_self_energy_at_frequency_point(
double *real_self_energy, const double frequency_point,
const Darray *fc3_normal_squared, const int64_t *band_indices,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplet_weights, const double epsilon,
const double temperature, const double unit_conversion_factor,
const double temperature_THz, const double unit_conversion_factor,
const double cutoff_frequency);
void ph3py_get_collision_matrix(
double *collision_matrix, const Darray *fc3_normal_squared,
@ -120,13 +123,13 @@ void ph3py_get_collision_matrix(
const int64_t *triplets_map, const int64_t *map_q,
const int64_t *rotated_grid_points, const double *rotations_cartesian,
const double *g, const int64_t num_ir_gp, const int64_t num_gp,
const int64_t num_rot, const double temperature,
const int64_t num_rot, const double temperature_THz,
const double unit_conversion_factor, const double cutoff_frequency);
void ph3py_get_reducible_collision_matrix(
double *collision_matrix, const Darray *fc3_normal_squared,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplets_map, const int64_t *map_q, const double *g,
const int64_t num_gp, const double temperature,
const int64_t num_gp, const double temperature_THz,
const double unit_conversion_factor, const double cutoff_frequency);
void ph3py_get_isotope_scattering_strength(
double *gamma, const int64_t grid_point, const int64_t *ir_grid_points,
@ -170,7 +173,8 @@ int64_t ph3py_get_BZ_triplets_at_q(
int64_t (*triplets)[3], const int64_t grid_point,
const int64_t (*bz_grid_addresses)[3], const int64_t *bz_map,
const int64_t *map_triplets, const int64_t num_map_triplets,
const int64_t D_diag[3], const int64_t Q[3][3], const int64_t bz_grid_type);
const int64_t D_diag[3], const int64_t Q[3][3],
const double reciprocal_lattice[3][3], const int64_t bz_grid_type);
int64_t ph3py_get_integration_weight(
double *iw, char *iw_zero, const double *frequency_points,
const int64_t num_band0, const int64_t relative_grid_address[24][4][3],

View File

@ -36,6 +36,5 @@
#define __phonoc_const_H__
#define M_2PI 6.283185307179586
#define KB 8.6173382568083159E-05
#endif

View File

@ -50,7 +50,7 @@
static void get_collision(
double *ise, const int64_t num_band0, const int64_t num_band,
const int64_t num_temps, const double *temperatures, const double *g,
const int64_t num_temps, const double *temperatures_THz, const double *g,
const char *g_zero, const double *frequencies,
const lapack_complex_double *eigenvectors, const int64_t triplet[3],
const int64_t triplet_weight, const RecgridConstBZGrid *bzgrid,
@ -72,9 +72,9 @@ void ppc_get_pp_collision(
const int64_t *triplet_weights, const RecgridConstBZGrid *bzgrid,
const double *fc3, const int64_t is_compact_fc3,
const AtomTriplets *atom_triplets, const double *masses,
const Larray *band_indices, const Darray *temperatures, const int64_t is_NU,
const int64_t symmetrize_fc3_q, const double cutoff_frequency,
const int64_t openmp_per_triplets) {
const Larray *band_indices, const Darray *temperatures_THz,
const int64_t is_NU, const int64_t symmetrize_fc3_q,
const double cutoff_frequency, const int64_t openmp_per_triplets) {
int64_t i;
int64_t num_band, num_band0, num_band_prod, num_temps;
double *ise, *freqs_at_gp, *g;
@ -89,7 +89,7 @@ void ppc_get_pp_collision(
num_band0 = band_indices->dims[0];
num_band = atom_triplets->multi_dims[1] * 3;
num_band_prod = num_band0 * num_band * num_band;
num_temps = temperatures->dims[0];
num_temps = temperatures_THz->dims[0];
ise =
(double *)malloc(sizeof(double) * num_triplets * num_temps * num_band0);
freqs_at_gp = (double *)malloc(sizeof(double) * num_band0);
@ -101,8 +101,8 @@ void ppc_get_pp_collision(
tpl_set_relative_grid_address(tp_relative_grid_address,
relative_grid_address, 2);
#ifdef _OPENMP
#pragma omp parallel for schedule(guided) private( \
g, g_zero) if (openmp_per_triplets)
#pragma omp parallel for schedule(guided) \
private(g, g_zero) if (openmp_per_triplets)
#endif
for (i = 0; i < num_triplets; i++) {
g = (double *)malloc(sizeof(double) * 2 * num_band_prod);
@ -115,7 +115,7 @@ void ppc_get_pp_collision(
num_band, 2, openmp_per_triplets);
get_collision(ise + i * num_temps * num_band0, num_band0, num_band,
num_temps, temperatures->data, g, g_zero, frequencies,
num_temps, temperatures_THz->data, g, g_zero, frequencies,
eigenvectors, triplets[i], triplet_weights[i], bzgrid,
fc3, is_compact_fc3, atom_triplets, masses,
band_indices->data, symmetrize_fc3_q, cutoff_frequency,
@ -143,9 +143,9 @@ void ppc_get_pp_collision_with_sigma(
const int64_t *triplet_weights, const RecgridConstBZGrid *bzgrid,
const double *fc3, const int64_t is_compact_fc3,
const AtomTriplets *atom_triplets, const double *masses,
const Larray *band_indices, const Darray *temperatures, const int64_t is_NU,
const int64_t symmetrize_fc3_q, const double cutoff_frequency,
const int64_t openmp_per_triplets) {
const Larray *band_indices, const Darray *temperatures_THz,
const int64_t is_NU, const int64_t symmetrize_fc3_q,
const double cutoff_frequency, const int64_t openmp_per_triplets) {
int64_t i;
int64_t num_band, num_band0, num_band_prod, num_temps;
int64_t const_adrs_shift;
@ -161,7 +161,7 @@ void ppc_get_pp_collision_with_sigma(
num_band0 = band_indices->dims[0];
num_band = atom_triplets->multi_dims[1] * 3;
num_band_prod = num_band0 * num_band * num_band;
num_temps = temperatures->dims[0];
num_temps = temperatures_THz->dims[0];
const_adrs_shift = num_band_prod;
ise =
@ -175,8 +175,8 @@ void ppc_get_pp_collision_with_sigma(
cutoff = sigma * sigma_cutoff;
#ifdef _OPENMP
#pragma omp parallel for schedule(guided) private( \
g, g_zero) if (openmp_per_triplets)
#pragma omp parallel for schedule(guided) \
private(g, g_zero) if (openmp_per_triplets)
#endif
for (i = 0; i < num_triplets; i++) {
g = (double *)malloc(sizeof(double) * 2 * num_band_prod);
@ -186,7 +186,7 @@ void ppc_get_pp_collision_with_sigma(
const_adrs_shift, frequencies, num_band, 2, 1);
get_collision(ise + i * num_temps * num_band0, num_band0, num_band,
num_temps, temperatures->data, g, g_zero, frequencies,
num_temps, temperatures_THz->data, g, g_zero, frequencies,
eigenvectors, triplets[i], triplet_weights[i], bzgrid,
fc3, is_compact_fc3, atom_triplets, masses,
band_indices->data, symmetrize_fc3_q, cutoff_frequency,
@ -209,7 +209,7 @@ void ppc_get_pp_collision_with_sigma(
static void get_collision(
double *ise, const int64_t num_band0, const int64_t num_band,
const int64_t num_temps, const double *temperatures, const double *g,
const int64_t num_temps, const double *temperatures_THz, const double *g,
const char *g_zero, const double *frequencies,
const lapack_complex_double *eigenvectors, const int64_t triplet[3],
const int64_t triplet_weight, const RecgridConstBZGrid *bzgrid,
@ -220,14 +220,14 @@ static void get_collision(
int64_t i;
int64_t num_band_prod, num_g_pos;
double *fc3_normal_squared;
int64_t(*g_pos)[4];
int64_t (*g_pos)[4];
fc3_normal_squared = NULL;
g_pos = NULL;
num_band_prod = num_band0 * num_band * num_band;
fc3_normal_squared = (double *)malloc(sizeof(double) * num_band_prod);
g_pos = (int64_t(*)[4])malloc(sizeof(int64_t[4]) * num_band_prod);
g_pos = (int64_t (*)[4])malloc(sizeof(int64_t[4]) * num_band_prod);
for (i = 0; i < num_band_prod; i++) {
fc3_normal_squared[i] = 0;
@ -243,8 +243,8 @@ static void get_collision(
ise_imag_self_energy_at_triplet(
ise, num_band0, num_band, fc3_normal_squared, frequencies, triplet,
triplet_weight, g, g + num_band_prod, g_pos, num_g_pos, temperatures,
num_temps, cutoff_frequency, openmp_per_triplets, 0);
triplet_weight, g, g + num_band_prod, g_pos, num_g_pos,
temperatures_THz, num_temps, cutoff_frequency, openmp_per_triplets, 0);
free(fc3_normal_squared);
fc3_normal_squared = NULL;

View File

@ -50,9 +50,9 @@ void ppc_get_pp_collision(
const int64_t *triplet_weights, const RecgridConstBZGrid *bzgrid,
const double *fc3, const int64_t is_compact_fc3,
const AtomTriplets *atom_triplets, const double *masses,
const Larray *band_indices, const Darray *temperatures, const int64_t is_NU,
const int64_t symmetrize_fc3_q, const double cutoff_frequency,
const int64_t openmp_per_triplets);
const Larray *band_indices, const Darray *temperatures_THz,
const int64_t is_NU, const int64_t symmetrize_fc3_q,
const double cutoff_frequency, const int64_t openmp_per_triplets);
void ppc_get_pp_collision_with_sigma(
double *imag_self_energy, const double sigma, const double sigma_cutoff,
const double *frequencies, const lapack_complex_double *eigenvectors,
@ -60,8 +60,8 @@ void ppc_get_pp_collision_with_sigma(
const int64_t *triplet_weights, const RecgridConstBZGrid *bzgrid,
const double *fc3, const int64_t is_compact_fc3,
const AtomTriplets *atom_triplets, const double *masses,
const Larray *band_indices, const Darray *temperatures, const int64_t is_NU,
const int64_t symmetrize_fc3_q, const double cutoff_frequency,
const int64_t openmp_per_triplets);
const Larray *band_indices, const Darray *temperatures_THz,
const int64_t is_NU, const int64_t symmetrize_fc3_q,
const double cutoff_frequency, const int64_t openmp_per_triplets);
#endif

View File

@ -46,12 +46,12 @@ static double get_real_self_energy_at_band(
const int64_t band_index, const Darray *fc3_normal_squared,
const double fpoint, const double *frequencies,
const int64_t (*triplets)[3], const int64_t *triplet_weights,
const double epsilon, const double temperature,
const double epsilon, const double temperature_THz,
const double unit_conversion_factor, const double cutoff_frequency);
static double sum_real_self_energy_at_band(
const int64_t num_band, const double *fc3_normal_squared,
const double fpoint, const double *freqs1, const double *freqs2,
const double epsilon, const double temperature,
const double epsilon, const double temperature_THz,
const double cutoff_frequency);
static double sum_real_self_energy_at_band_0K(
const int64_t num_band, const double *fc3_normal_squared,
@ -62,7 +62,7 @@ void rse_get_real_self_energy_at_bands(
double *real_self_energy, const Darray *fc3_normal_squared,
const int64_t *band_indices, const double *frequencies,
const int64_t (*triplets)[3], const int64_t *triplet_weights,
const double epsilon, const double temperature,
const double epsilon, const double temperature_THz,
const double unit_conversion_factor, const double cutoff_frequency) {
int64_t i, num_band0, num_band, gp0;
double fpoint;
@ -79,8 +79,8 @@ void rse_get_real_self_energy_at_bands(
} else {
real_self_energy[i] = get_real_self_energy_at_band(
i, fc3_normal_squared, fpoint, frequencies, triplets,
triplet_weights, epsilon, temperature, unit_conversion_factor,
cutoff_frequency);
triplet_weights, epsilon, temperature_THz,
unit_conversion_factor, cutoff_frequency);
}
}
}
@ -90,7 +90,7 @@ void rse_get_real_self_energy_at_frequency_point(
const Darray *fc3_normal_squared, const int64_t *band_indices,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplet_weights, const double epsilon,
const double temperature, const double unit_conversion_factor,
const double temperature_THz, const double unit_conversion_factor,
const double cutoff_frequency) {
int64_t i, num_band0;
@ -103,8 +103,8 @@ void rse_get_real_self_energy_at_frequency_point(
} else {
real_self_energy[i] = get_real_self_energy_at_band(
i, fc3_normal_squared, frequency_point, frequencies, triplets,
triplet_weights, epsilon, temperature, unit_conversion_factor,
cutoff_frequency);
triplet_weights, epsilon, temperature_THz,
unit_conversion_factor, cutoff_frequency);
}
}
}
@ -113,7 +113,7 @@ static double get_real_self_energy_at_band(
const int64_t band_index, const Darray *fc3_normal_squared,
const double fpoint, const double *frequencies,
const int64_t (*triplets)[3], const int64_t *triplet_weights,
const double epsilon, const double temperature,
const double epsilon, const double temperature_THz,
const double unit_conversion_factor, const double cutoff_frequency) {
int64_t i, num_triplets, num_band0, num_band, gp1, gp2;
double shift;
@ -129,14 +129,14 @@ static double get_real_self_energy_at_band(
for (i = 0; i < num_triplets; i++) {
gp1 = triplets[i][1];
gp2 = triplets[i][2];
if (temperature > 0) {
if (temperature_THz > 0) {
shift += sum_real_self_energy_at_band(
num_band,
fc3_normal_squared->data +
i * num_band0 * num_band * num_band +
band_index * num_band * num_band,
fpoint, frequencies + gp1 * num_band,
frequencies + gp2 * num_band, epsilon, temperature,
frequencies + gp2 * num_band, epsilon, temperature_THz,
cutoff_frequency) *
triplet_weights[i] * unit_conversion_factor;
} else {
@ -157,7 +157,7 @@ static double get_real_self_energy_at_band(
static double sum_real_self_energy_at_band(
const int64_t num_band, const double *fc3_normal_squared,
const double fpoint, const double *freqs1, const double *freqs2,
const double epsilon, const double temperature,
const double epsilon, const double temperature_THz,
const double cutoff_frequency) {
int64_t i, j;
double n1, n2, f1, f2, f3, f4, shift;
@ -166,10 +166,10 @@ static double sum_real_self_energy_at_band(
shift = 0;
for (i = 0; i < num_band; i++) {
if (freqs1[i] > cutoff_frequency) {
n1 = funcs_bose_einstein(freqs1[i], temperature);
n1 = funcs_bose_einstein(freqs1[i], temperature_THz);
for (j = 0; j < num_band; j++) {
if (freqs2[j] > cutoff_frequency) {
n2 = funcs_bose_einstein(freqs2[j], temperature);
n2 = funcs_bose_einstein(freqs2[j], temperature_THz);
f1 = fpoint + freqs1[i] + freqs2[j];
f2 = fpoint - freqs1[i] - freqs2[j];
f3 = fpoint - freqs1[i] + freqs2[j];

View File

@ -45,12 +45,12 @@ void rse_get_real_self_energy_at_bands(
double *real_self_energy, const Darray *fc3_normal_squared,
const int64_t *band_indices, const double *frequencies,
const int64_t (*triplets)[3], const int64_t *triplet_weights,
const double epsilon, const double temperature,
const double epsilon, const double temperature_THz,
const double unit_conversion_factor, const double cutoff_frequency);
void rse_get_real_self_energy_at_frequency_point(
double *real_self_energy, const double frequency_point,
const Darray *fc3_normal_squared, const int64_t *band_indices,
const double *frequencies, const int64_t (*triplets)[3],
const int64_t *triplet_weights, const double epsilon,
const double temperature, const double unit_conversion_factor,
const double temperature_THz, const double unit_conversion_factor,
const double cutoff_frequency);

View File

@ -75,7 +75,7 @@ static lapack_complex_double get_pre_phase_factor(
static lapack_complex_double sum_lapack_complex_double(lapack_complex_double a,
lapack_complex_double b);
/* fc3_reciprocal[num_patom, num_patom, num_patom, 3, 3, 3] */
/* fc3_reciprocal[num_patom, 3, num_patom, 3, num_patom, 3] */
void r2r_real_to_reciprocal(lapack_complex_double *fc3_reciprocal,
const double q_vecs[3][3], const double *fc3,
const int64_t is_compact_fc3,
@ -277,7 +277,7 @@ static void real_to_reciprocal_elements(
const int64_t pi0, const int64_t pi1, const int64_t pi2,
const int64_t leg_index) {
int64_t i, j, k, l;
int64_t num_satom, adrs_shift;
int64_t num_satom, adrs_shift_atoms, adrs_shift_fc3;
lapack_complex_double phase_factor;
double fc3_rec_real[27], fc3_rec_imag[27];
@ -309,8 +309,11 @@ static void real_to_reciprocal_elements(
continue;
}
}
adrs_shift =
i * 27 * num_satom * num_satom + j * 27 * num_satom + k * 27;
adrs_shift_atoms = i * num_satom * num_satom + j * num_satom + k;
if (!atom_triplets->nonzero_indices[adrs_shift_atoms]) {
continue;
}
adrs_shift_fc3 = adrs_shift_atoms * 27;
phase_factor =
phonoc_complex_prod(phase_factor1[j], phase_factor2[k]);
@ -320,19 +323,19 @@ static void real_to_reciprocal_elements(
for (l = 0; l < 27; l++) {
fc3_rec_real[l] +=
lapack_complex_double_real(phase_factor) *
fc3[adrs_shift + l] * 3;
fc3[adrs_shift_fc3 + l] * 3;
fc3_rec_imag[l] +=
lapack_complex_double_imag(phase_factor) *
fc3[adrs_shift + l] * 3;
fc3[adrs_shift_fc3 + l] * 3;
}
} else {
for (l = 0; l < 27; l++) {
fc3_rec_real[l] +=
lapack_complex_double_real(phase_factor) *
fc3[adrs_shift + l];
fc3[adrs_shift_fc3 + l];
fc3_rec_imag[l] +=
lapack_complex_double_imag(phase_factor) *
fc3[adrs_shift + l];
fc3[adrs_shift_fc3 + l];
}
}
}

View File

@ -48,6 +48,7 @@ typedef struct {
const int64_t *s2p_map;
int64_t make_r0_average;
const char *all_shortest;
const char *nonzero_indices; // for compact fc3
} AtomTriplets;
void r2r_real_to_reciprocal(lapack_complex_double *fc3_reciprocal,

View File

@ -193,20 +193,11 @@ double recgrid_get_tolerance_for_BZ_reduction(const RecgridBZGrid *bzgrid) {
int64_t i, j;
double tolerance;
double length[3];
double reclatQ[3][3];
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
reclatQ[i][j] = bzgrid->reclat[i][0] * bzgrid->Q[0][j] +
bzgrid->reclat[i][1] * bzgrid->Q[1][j] +
bzgrid->reclat[i][2] * bzgrid->Q[2][j];
}
}
for (i = 0; i < 3; i++) {
length[i] = 0;
for (j = 0; j < 3; j++) {
length[i] += reclatQ[j][i] * reclatQ[j][i];
length[i] += bzgrid->reclat[j][i] * bzgrid->reclat[j][i];
}
length[i] /= bzgrid->D_diag[i] * bzgrid->D_diag[i];
}
@ -233,8 +224,8 @@ RecgridMats *recgrid_alloc_RotMats(const int64_t size) {
rotmats->size = size;
if (size > 0) {
if ((rotmats->mat = (int64_t(*)[3][3])malloc(sizeof(int64_t[3][3]) *
size)) == NULL) {
if ((rotmats->mat = (int64_t (*)[3][3])malloc(sizeof(int64_t[3][3]) *
size)) == NULL) {
warning_print("Memory could not be allocated ");
warning_print("(RecgridMats, line %d, %s).\n", __LINE__, __FILE__);
free(rotmats);

View File

@ -198,7 +198,7 @@ int64_t recgrid_get_reciprocal_point_group(int64_t rec_rotations[48][3][3],
/**
* @brief Return D, P, Q of Smith normal form of A.
*
* @param D_diag Diagonal elements of diagnoal matrix D
* @param D_diag Diagonal elements of diagonal matrix D
* @param P Unimodular matrix P
* @param Q Unimodular matrix Q
* @param A Integer matrix
@ -215,7 +215,7 @@ int64_t recgrid_get_snf3x3(int64_t D_diag[3], int64_t P[3][3], int64_t Q[3][3],
* {tilde-R^T}
* @param rotations Original rotations matrices in reciprocal space {R^T}
* @param num_rot Number of rotation matrices
* @param D_diag Diagonal elements of diagnoal matrix D of Smith normal form
* @param D_diag Diagonal elements of diagonal matrix D of Smith normal form
* @param Q Unimodular matrix Q of Smith normal form
* @return int64_t
*/
@ -232,7 +232,7 @@ int64_t recgrid_transform_rotations(int64_t (*transformed_rots)[3][3],
* array size of prod(D_diag)
* @param rotations Transformed rotation matrices in reciprocal space
* @param num_rot Number of rotation matrices
* @param D_diag Diagonal elements of diagnoal matrix D of Smith normal form
* @param D_diag Diagonal elements of diagonal matrix D of Smith normal form
* @param PS Shift in GR-grid
* @return int64_t Number of ir_grid_points.
*/
@ -252,7 +252,7 @@ int64_t recgrid_get_ir_grid_map(int64_t *ir_grid_map,
* @param bzg2grg Mapping table of bz_grid_addresses to gr_grid_addresses. In
* type-II, len(bzg2grg) == len(bz_grid_addresses) <= (D_diag[0] + 1) *
* (D_diag[1] + 1) * (D_diag[2] + 1).
* @param D_diag Diagonal elements of diagnoal matrix D of Smith normal form
* @param D_diag Diagonal elements of diagonal matrix D of Smith normal form
* @param Q Unimodular matrix Q of Smith normal form
* @param PS Shift in GR-grid
* @param rec_lattice Reduced reciprocal basis vectors in column vectors
@ -270,7 +270,7 @@ int64_t recgrid_get_bz_grid_addresses(
*
* @param bz_grid_index BZ grid point index
* @param rotation Transformed rotation in reciprocal space tilde-R^T
* @param bz_grid_addresses BZ grid point adddresses
* @param bz_grid_addresses BZ grid point addresses
* @param bz_map List of accumulated numbers of BZ grid points from the
* first GR grid point to the last grid point. In type-II, [0, 1, 3, 4, ...]
* means multiplicities of [1, 2, 1, ...], with len(bz_map)=product(D_diag) + 1.

View File

@ -49,16 +49,28 @@
#include "lapack_wrapper.h"
#ifdef MEASURE_R2N
#include <time.h>
#include <unistd.h>
#endif
static double get_fc3_sum(const lapack_complex_double *e0,
const lapack_complex_double *e1,
static void get_fc3_e0_e1_e2(
double *fc3_normal_squared, const int64_t (*g_pos)[4],
const int64_t num_g_pos, const lapack_complex_double *fc3_reciprocal,
const double *freqs0, const double *freqs1, const double *freqs2,
const lapack_complex_double *e0, const lapack_complex_double *e1,
const lapack_complex_double *e2, const int64_t *band_indices,
const int64_t num_band0, const int64_t num_band,
const double cutoff_frequency, const int64_t openmp_per_triplets);
static void get_fc3_e0(lapack_complex_double *fc3_e0,
const lapack_complex_double *fc3_reciprocal,
const lapack_complex_double *e0,
const int64_t band_index_0, const int64_t num_band);
static double get_fc3_sum(const lapack_complex_double *e1,
const lapack_complex_double *e2,
const lapack_complex_double *fc3_reciprocal,
const int64_t num_band);
static double get_fc3_sum_blas_like(const lapack_complex_double *e0,
const lapack_complex_double *e1,
const lapack_complex_double *e2,
const lapack_complex_double *fc3_reciprocal,
const int64_t num_band);
// Testing efficiency of BLAS
#ifdef MULTITHREADED_BLAS
static double get_fc3_sum_blas(const lapack_complex_double *e0,
const lapack_complex_double *e1,
@ -66,11 +78,7 @@ static double get_fc3_sum_blas(const lapack_complex_double *e0,
const lapack_complex_double *fc3_reciprocal,
const int64_t num_band);
#endif
static double get_fc3_sum_blas_like(const lapack_complex_double *e0,
const lapack_complex_double *e1,
const lapack_complex_double *e2,
const lapack_complex_double *fc3_reciprocal,
const int64_t num_band);
void reciprocal_to_normal_squared(
double *fc3_normal_squared, const int64_t (*g_pos)[4],
const int64_t num_g_pos, const lapack_complex_double *fc3_reciprocal,
@ -78,17 +86,19 @@ void reciprocal_to_normal_squared(
const lapack_complex_double *eigvecs0,
const lapack_complex_double *eigvecs1,
const lapack_complex_double *eigvecs2, const double *masses,
const int64_t *band_indices, const int64_t num_band,
const double cutoff_frequency, const int64_t openmp_per_triplets) {
int64_t i, j, ij, num_atom, use_multithreaded_blas;
const int64_t *band_indices, const int64_t num_band0,
const int64_t num_band, const double cutoff_frequency,
const int64_t openmp_per_triplets) {
int64_t i, j, ij, num_atom;
double *inv_sqrt_masses;
lapack_complex_double *e0, *e1, *e2;
/* Inverse sqrt mass is multipled with eigenvectors to reduce number
* of */
/* operations in get_fc3_sum. Three eigenvector matrices are looped
* by */
/* first loop leveraging contiguous memory layout of [e0, e1, e2].
/* Inverse sqrt mass is multiplied with eigenvectors to reduce
* number of */
/* operations in get_fc3_sum. Three eigenvector matrices are
* looped by */
/* first loop leveraging contiguous memory layout of [e0,
* e1, e2].
*/
num_atom = num_band / 3;
inv_sqrt_masses = (double *)malloc(sizeof(double) * num_band);
@ -132,64 +142,10 @@ void reciprocal_to_normal_squared(
free(inv_sqrt_masses);
inv_sqrt_masses = NULL;
#ifdef MEASURE_R2N
double loopTotalCPUTime, loopTotalWallTime;
time_t loopStartWallTime;
clock_t loopStartCPUTime;
#endif
#ifdef MEASURE_R2N
loopStartWallTime = time(NULL);
loopStartCPUTime = clock();
#endif
#ifdef MULTITHREADED_BLAS
if (openmp_per_triplets) {
use_multithreaded_blas = 0;
} else {
use_multithreaded_blas = 1;
}
#else
use_multithreaded_blas = 0;
#ifdef _OPENMP
#pragma omp parallel for if (!openmp_per_triplets)
#endif
#endif
for (i = 0; i < num_g_pos; i++) {
if (freqs0[band_indices[g_pos[i][0]]] > cutoff_frequency &&
freqs1[g_pos[i][1]] > cutoff_frequency &&
freqs2[g_pos[i][2]] > cutoff_frequency) {
#ifdef MULTITHREADED_BLAS
if (use_multithreaded_blas) {
fc3_normal_squared[g_pos[i][3]] =
get_fc3_sum_blas(e0 + band_indices[g_pos[i][0]] * num_band,
e1 + g_pos[i][1] * num_band,
e2 + g_pos[i][2] * num_band,
fc3_reciprocal, num_band) /
(freqs0[band_indices[g_pos[i][0]]] * freqs1[g_pos[i][1]] *
freqs2[g_pos[i][2]]);
} else {
#endif
fc3_normal_squared[g_pos[i][3]] =
get_fc3_sum_blas_like(
e0 + band_indices[g_pos[i][0]] * num_band,
e1 + g_pos[i][1] * num_band,
e2 + g_pos[i][2] * num_band, fc3_reciprocal, num_band) /
(freqs0[band_indices[g_pos[i][0]]] * freqs1[g_pos[i][1]] *
freqs2[g_pos[i][2]]);
#ifdef MULTITHREADED_BLAS
}
#endif
} else {
fc3_normal_squared[g_pos[i][3]] = 0;
}
}
#ifdef MEASURE_R2N
loopTotalCPUTime = (double)(clock() - loopStartCPUTime) / CLOCKS_PER_SEC;
loopTotalWallTime = difftime(time(NULL), loopStartWallTime);
printf(" %1.3fs (%1.3fs CPU)\n", loopTotalWallTime, loopTotalCPUTime);
#endif
get_fc3_e0_e1_e2(fc3_normal_squared, g_pos, num_g_pos, fc3_reciprocal,
freqs0, freqs1, freqs2, e0, e1, e2, band_indices,
num_band0, num_band, cutoff_frequency,
openmp_per_triplets);
free(e0);
e0 = NULL;
@ -197,41 +153,158 @@ void reciprocal_to_normal_squared(
e2 = NULL;
}
static double get_fc3_sum(const lapack_complex_double *e0,
const lapack_complex_double *e1,
// This is less efficient than the one without multithreading
// but can be called when unit cell is large.
static void get_fc3_e0_e1_e2(
double *fc3_normal_squared, const int64_t (*g_pos)[4],
const int64_t num_g_pos, const lapack_complex_double *fc3_reciprocal,
const double *freqs0, const double *freqs1, const double *freqs2,
const lapack_complex_double *e0, const lapack_complex_double *e1,
const lapack_complex_double *e2, const int64_t *band_indices,
const int64_t num_band0, const int64_t num_band,
const double cutoff_frequency, const int64_t openmp_per_triplets) {
int64_t i;
lapack_complex_double *fc3_e0, zero;
zero = lapack_make_complex_double(0, 0);
fc3_e0 = (lapack_complex_double *)malloc(sizeof(lapack_complex_double) *
num_band0 * num_band * num_band);
for (i = 0; i < num_band0 * num_band * num_band; i++) {
fc3_e0[i] = zero;
}
#ifdef _OPENMP
#pragma omp parallel for if (!openmp_per_triplets)
#endif
for (i = 0; i < num_band0; i++) {
get_fc3_e0(fc3_e0 + i * num_band * num_band, fc3_reciprocal, e0,
band_indices[i], num_band);
}
#ifdef _OPENMP
#pragma omp parallel for if (!openmp_per_triplets)
#endif
for (i = 0; i < num_g_pos; i++) {
if (freqs0[band_indices[g_pos[i][0]]] > cutoff_frequency &&
freqs1[g_pos[i][1]] > cutoff_frequency &&
freqs2[g_pos[i][2]] > cutoff_frequency) {
fc3_normal_squared[g_pos[i][3]] =
get_fc3_sum(
e1 + g_pos[i][1] * num_band, e2 + g_pos[i][2] * num_band,
fc3_e0 + g_pos[i][0] * num_band * num_band, num_band) /
(freqs0[band_indices[g_pos[i][0]]] * freqs1[g_pos[i][1]] *
freqs2[g_pos[i][2]]);
} else {
fc3_normal_squared[g_pos[i][3]] = 0;
}
}
free(fc3_e0);
fc3_e0 = NULL;
}
static void get_fc3_e0(lapack_complex_double *fc3_e0,
const lapack_complex_double *fc3_reciprocal,
const lapack_complex_double *e0,
const int64_t band_index_0, const int64_t num_band) {
int64_t j, k;
lapack_complex_double fc3_elem;
for (j = 0; j < num_band; j++) {
for (k = 0; k < num_band * num_band; k++) {
fc3_elem =
phonoc_complex_prod(fc3_reciprocal[j * num_band * num_band + k],
e0[band_index_0 * num_band + j]);
fc3_e0[k] = lapack_make_complex_double(
lapack_complex_double_real(fc3_e0[k]) +
lapack_complex_double_real(fc3_elem),
lapack_complex_double_imag(fc3_e0[k]) +
lapack_complex_double_imag(fc3_elem));
}
}
}
static double get_fc3_sum(const lapack_complex_double *e1,
const lapack_complex_double *e2,
const lapack_complex_double *fc3_reciprocal,
const lapack_complex_double *fc3_e0,
const int64_t num_band) {
int64_t i, j, jk;
int64_t i, j;
double sum_real, sum_imag;
lapack_complex_double e_012_fc3, fc3_i_e_12, *e_12_cache;
const lapack_complex_double *fc3_i;
lapack_complex_double *fc3_e0_e1, fc3_elem;
e_12_cache = (lapack_complex_double *)malloc(sizeof(lapack_complex_double) *
num_band * num_band);
fc3_e0_e1 = (lapack_complex_double *)malloc(sizeof(lapack_complex_double) *
num_band);
for (i = 0; i < num_band; i++) {
fc3_e0_e1[i] = lapack_make_complex_double(0, 0);
}
for (i = 0; i < num_band; i++) {
for (j = 0; j < num_band; j++) {
fc3_elem = phonoc_complex_prod(fc3_e0[i * num_band + j], e1[i]);
fc3_e0_e1[j] = lapack_make_complex_double(
lapack_complex_double_real(fc3_e0_e1[j]) +
lapack_complex_double_real(fc3_elem),
lapack_complex_double_imag(fc3_e0_e1[j]) +
lapack_complex_double_imag(fc3_elem));
}
}
sum_real = 0;
sum_imag = 0;
for (i = 0; i < num_band; i++) {
for (j = 0; j < num_band; j++) {
e_12_cache[i * num_band + j] = phonoc_complex_prod(e1[i], e2[j]);
}
fc3_elem = phonoc_complex_prod(fc3_e0_e1[i], e2[i]);
sum_real += lapack_complex_double_real(fc3_elem);
sum_imag += lapack_complex_double_imag(fc3_elem);
}
free(fc3_e0_e1);
fc3_e0_e1 = NULL;
return (sum_real * sum_real + sum_imag * sum_imag);
}
static double get_fc3_sum_blas_like(const lapack_complex_double *e0,
const lapack_complex_double *e1,
const lapack_complex_double *e2,
const lapack_complex_double *fc3_reciprocal,
const int64_t num_band) {
int64_t i, j;
double sum_real, sum_imag, retval_real, retval_imag;
lapack_complex_double *e_12, fc3_e_12, fc3_e_012;
e_12 = (lapack_complex_double *)malloc(sizeof(lapack_complex_double) *
num_band * num_band);
for (i = 0; i < num_band; i++) {
fc3_i = fc3_reciprocal + i * num_band * num_band;
for (jk = 0; jk < num_band * num_band; jk++) {
fc3_i_e_12 = phonoc_complex_prod(fc3_i[jk], e_12_cache[jk]);
e_012_fc3 = phonoc_complex_prod(e0[i], fc3_i_e_12);
sum_real += lapack_complex_double_real(e_012_fc3);
sum_imag += lapack_complex_double_imag(e_012_fc3);
memcpy(e_12 + i * num_band, e2,
sizeof(lapack_complex_double) * num_band);
for (j = 0; j < num_band; j++) {
e_12[i * num_band + j] =
phonoc_complex_prod(e1[i], e_12[i * num_band + j]);
}
}
free(e_12_cache);
e_12_cache = NULL;
return (sum_real * sum_real + sum_imag * sum_imag);
retval_real = 0;
retval_imag = 0;
for (i = 0; i < num_band; i++) {
sum_real = 0;
sum_imag = 0;
for (j = 0; j < num_band * num_band; j++) {
fc3_e_12 = phonoc_complex_prod(
fc3_reciprocal[i * num_band * num_band + j], e_12[j]);
sum_real += lapack_complex_double_real(fc3_e_12);
sum_imag += lapack_complex_double_imag(fc3_e_12);
}
fc3_e_012 = phonoc_complex_prod(
e0[i], lapack_make_complex_double(sum_real, sum_imag));
retval_real += lapack_complex_double_real(fc3_e_012);
retval_imag += lapack_complex_double_imag(fc3_e_012);
}
free(e_12);
e_12 = NULL;
return retval_real * retval_real + retval_imag * retval_imag;
}
#ifdef MULTITHREADED_BLAS
@ -271,46 +344,3 @@ static double get_fc3_sum_blas(const lapack_complex_double *e0,
lapack_complex_double_imag(retval);
}
#endif
static double get_fc3_sum_blas_like(const lapack_complex_double *e0,
const lapack_complex_double *e1,
const lapack_complex_double *e2,
const lapack_complex_double *fc3_reciprocal,
const int64_t num_band) {
int64_t i, j;
double sum_real, sum_imag, retval_real, retval_imag;
lapack_complex_double *e_12, fc3_e_12, fc3_e_012;
e_12 = (lapack_complex_double *)malloc(sizeof(lapack_complex_double) *
num_band * num_band);
for (i = 0; i < num_band; i++) {
memcpy(e_12 + i * num_band, e2, 16 * num_band);
for (j = 0; j < num_band; j++) {
e_12[i * num_band + j] =
phonoc_complex_prod(e1[i], e_12[i * num_band + j]);
}
}
retval_real = 0;
retval_imag = 0;
for (i = 0; i < num_band; i++) {
sum_real = 0;
sum_imag = 0;
for (j = 0; j < num_band * num_band; j++) {
fc3_e_12 = phonoc_complex_prod(
fc3_reciprocal[i * num_band * num_band + j], e_12[j]);
sum_real += lapack_complex_double_real(fc3_e_12);
sum_imag += lapack_complex_double_imag(fc3_e_12);
}
fc3_e_012 = phonoc_complex_prod(
e0[i], lapack_make_complex_double(sum_real, sum_imag));
retval_real += lapack_complex_double_real(fc3_e_012);
retval_imag += lapack_complex_double_imag(fc3_e_012);
}
free(e_12);
e_12 = NULL;
return retval_real * retval_real + retval_imag * retval_imag;
}

View File

@ -46,7 +46,8 @@ void reciprocal_to_normal_squared(
const lapack_complex_double *eigvecs0,
const lapack_complex_double *eigvecs1,
const lapack_complex_double *eigvecs2, const double *masses,
const int64_t *band_indices, const int64_t num_band,
const double cutoff_frequency, const int64_t openmp_per_triplets);
const int64_t *band_indices, const int64_t num_band0,
const int64_t num_band, const double cutoff_frequency,
const int64_t openmp_per_triplets);
#endif

View File

@ -1,7 +1,7 @@
/* Copyright (C) 2015 Atsushi Togo */
/* All rights reserved. */
/* These codes were originally parts of spglib, but only develped */
/* These codes were originally parts of spglib, but only developed */
/* and used for phono3py. Therefore these were moved from spglib to */
/* phono3py. This file is part of phonopy. */

View File

@ -1,7 +1,7 @@
/* Copyright (C) 2015 Atsushi Togo */
/* All rights reserved. */
/* Some of these codes were originally parts of spglib, but only develped */
/* Some of these codes were originally parts of spglib, but only developed */
/* and used for phono3py. Therefore these were moved from spglib to */
/* phono3py. This file is part of phonopy. */

View File

@ -1,7 +1,7 @@
/* Copyright (C) 2015 Atsushi Togo */
/* All rights reserved. */
/* These codes were originally parts of spglib, but only develped */
/* These codes were originally parts of spglib, but only developed */
/* and used for phono3py. Therefore these were moved from spglib to */
/* phono3py. This file is part of phonopy. */
@ -262,7 +262,7 @@ static void get_BZ_triplets_at_q_type1(int64_t (*triplets)[3],
int64_t bzgp[3], G[3];
int64_t bz_adrs0[3], bz_adrs1[3], bz_adrs2[3];
const int64_t *gp_map;
const int64_t(*bz_adrs)[3];
const int64_t (*bz_adrs)[3];
double d2, min_d2, tolerance;
double LQD_inv[3][3];
@ -348,13 +348,14 @@ static void get_BZ_triplets_at_q_type2(int64_t (*triplets)[3],
int64_t bzgp[3], G[3];
int64_t bz_adrs0[3], bz_adrs1[3], bz_adrs2[3];
const int64_t *gp_map;
const int64_t(*bz_adrs)[3];
const int64_t (*bz_adrs)[3];
double d2, min_d2, tolerance;
double LQD_inv[3][3];
gp_map = bzgrid->gp_map;
bz_adrs = bzgrid->addresses;
get_LQD_inv(LQD_inv, bzgrid);
/* This tolerance is used to be consistent to BZ reduction in bzgrid. */
tolerance = recgrid_get_tolerance_for_BZ_reduction((RecgridBZGrid *)bzgrid);
@ -423,10 +424,15 @@ static void get_LQD_inv(double LQD_inv[3][3],
int64_t i, j, k;
/* LQD^-1 */
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
LQD_inv[i][j] = 0;
}
}
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
for (k = 0; k < 3; k++) {
LQD_inv[i][k] =
LQD_inv[i][k] +=
bzgrid->reclat[i][j] * bzgrid->Q[j][k] / bzgrid->D_diag[k];
}
}

View File

@ -1,7 +1,7 @@
/* Copyright (C) 2015 Atsushi Togo */
/* All rights reserved. */
/* These codes were originally parts of spglib, but only develped */
/* These codes were originally parts of spglib, but only developed */
/* and used for phono3py. Therefore these were moved from spglib to */
/* phono3py. This file is part of phonopy. */

View File

@ -195,7 +195,7 @@ void tpi_get_integration_weight_with_sigma(
}
/**
* @brief Return grid points of relative grid adddresses in BZ-grid
* @brief Return grid points of relative grid addresses in BZ-grid
*
* @param neighboring_grid_points Grid points of relative grid addresses in
* BZ-grid.

View File

@ -4,30 +4,33 @@ This directory contains python-sphinx documentation source.
## How to compile
```
```bash
make html
```
## Source files
* `conf.py` contains the sphinx setting confiuration.
* `conf.py` contains the sphinx setting configuration.
* `*.rst` are the usual sphinx documentation source and the filenames without `.rst` are the keys to link from toctree mainly in `index.rst`.
## How to publish
Web page files are copied to `gh-pages` branch. At the phono3py github top directory,
```
```bash
git checkout gh-pages
rm -r .buildinfo .doctrees *
```
From the directory the sphinx doc is complied,
```
```bash
rsync -avh _build/ <phono3py-repository-directory>/
```
Again, at the phono3py github top directory,
```
```bash
git add .
git commit -a -m "Update documentation ..."
git push

View File

@ -102,7 +102,7 @@ Number of points to be sampled in the x-axis.
### Options for tensor properties
For cummulative thermal conductivity, the last value is given as the thermal
For cumulative thermal conductivity, the last value is given as the thermal
conductivity in W/mK. For the other properties, the last value is effectively
the sum of values on all mesh grids divided by number of mesh grids. This is
understood as normalized for one primitive cell. Before version 1.11.13.1, the

View File

@ -2,6 +2,49 @@
# Change Log
## Jul-22-2025: Version 3.18.0
- Changed `Phono3py.run_imag_self_energy()` to return `ImagSelfEnergyValues`.
- Traditional force constants symmetrizer now applies translational and
permutation symmetries alternately 3 times in succession (previously once).
## Jul-5-2025: Version 3.17.1
- Fix direct-solution crashing when executed via command line
## Jun-26-2025: Version 3.17.0
- Major refactoring of command-user interface. Most of routines behind the
`phono3py` and `phono3py-load` commands were unified.
- For `phono3py-load`, symfc-projector is used to symmetrize force constants
calculated by finite difference approach as the default behavior. The previous
behavior of the symmetrization can be recovered by `--fc-calculator
traditional` option.
## Jun-12-2025: Version 3.16.0
- Release to follow the change of phonopy
## Apr-30-2025: Version 3.15.1
- Release to follow the change of phonopy
## Mar-4-2025: Version 3.15.0
- Release to follow the change of phonopy
## Mar-1-2025: Version 3.14.1
- Release to follow the change of phonopy
## Feb-7-2025: Version 3.14.0
- Release to follow the change of phonopy
## Feb-5-2025: Version 3.13.0
- Release to follow the change of phonopy
## Feb-1-2025: Version 3.12.2
- Fix an openmp related bug in computing collision matrix in C
@ -147,7 +190,7 @@ This is a major version release. There are backward-incompatible changes.
- Calculation method to transform supercell third-order force constants fc3 in
real to reciprocal space was changed as described at {ref}`changelog_v290`.
This results in the change of results with respect to those obtained by
phono3py version 2. To emulate v2 behaviour, use `--v2` option in phono3py
phono3py version 2. To emulate v2 behavior, use `--v2` option in phono3py
command line script. For `Phono3py` class , `make_r0_average=True` (default)
when instantiating it, and similarly for `phono3py.load` function.
- Completely dropped support of `disp_fc3.yaml` and `disp_fc2.yaml`.
@ -175,7 +218,7 @@ This is a major version release. There are backward-incompatible changes.
## Dec-25-2023: Version 2.9.0
- Pre-release of version 3.0.
- `--v3` option enables phono3py version 3 behaviour. In phono3py-v3, it is
- `--v3` option enables phono3py version 3 behavior. In phono3py-v3, it is
planned to replace $\sum_{l'l''}\Phi_{\alpha\beta\gamma}(0\kappa, l'\kappa',
l''\kappa'') \cdots$ in Eq.(41) of
<https://journals.jps.jp/doi/10.7566/JPSJ.92.012001> by
@ -235,7 +278,7 @@ This is a major version release. There are backward-incompatible changes.
- Installation using `setup.py` now requires creating `site.cfg` file. See
<https://phonopy.github.io/phono3py/install.html> and
[PR #59](https://github.com/phonopy/phono3py/pull/59).
- Dorp python 3.6 support, and dependencies of numpy and matplotlib versions are
- Drop python 3.6 support, and dependencies of numpy and matplotlib versions are
updated:
- Python >= 3.7
@ -265,9 +308,9 @@ This is a major version release. There are some backward-incompatible changes.
from `dtype='intc'`.
3. Python 3.5 or later is required.
To emulate the version 1.x behaviour in `phono3py` command, try `--v1` option.
To emurate the version 1.x behaviour in API, specify `store_dense_gp_map=False`
and `store_dense_svecs=False` in instatiation of `Phono3py` class or phon3py
To emulate the version 1.x behavior in `phono3py` command, try `--v1` option.
To emurate the version 1.x behavior in API, specify `store_dense_gp_map=False`
and `store_dense_svecs=False` in instantiation of `Phono3py` class or phono3py
loader.
## Mar-17-2021: Version 1.22.3
@ -281,7 +324,7 @@ loader.
## Feb-21-2021: Version 1.22.1
- `phono3py` command didn't work. This was fixed.
- Fix behaviour when specifying `--thm` and `--sigma` simultaneously.
- Fix behavior when specifying `--thm` and `--sigma` simultaneously.
## Jan-29-2021: Version 1.22.0
@ -337,8 +380,7 @@ loader.
`FORCES_FC3` is assumed.
- TURBOMOLE interface is provided by Antti Karttunen (`--turbomole`).
- Compatibility of `fc2.hdf5` and `force_constants.hdf5` was improved for all
calculators to store physical unit information in the hdf5 file. See
{ref}`file_format_compatibility`.
calculators to store physical unit information in the hdf5 file.
## Mar-24-2019: Version 1.16.0
@ -366,7 +408,7 @@ loader.
- Update to work with phonopy v1.14.2.
- Ph-ph interaction can be read (`--read-pp`) and write (`--write-pp`) in RTA
thermal conductivity calculation, too. Mind that the data stored are different
with and without `--full-pp`. Wihtout `--full-pp` the data are stored in
with and without `--full-pp`. Without `--full-pp` the data are stored in
complicated way to save data side, so it is not considered readable by usual
users.
@ -395,7 +437,7 @@ loader.
- `--sym-fc` option is added. This is just an alias to specify both `--sym-fc3r`
and `--sym-fc2` together.
- Documentation on `--write-phonon` and `--read-phonon` options is written.
These options are used to save harmonic phonon infromation on strage.
These options are used to save harmonic phonon information on storage.
## Nov-22-2017: version 1.12.5
@ -410,7 +452,7 @@ loader.
(3) happens when the primitive cell is relatively large. Number of triplets
can be shown using `--stp` option. A race condition of OpenMP multithreading
is the source of the bug. Therefore, if it occurs, the same calculation comes
up with the different thermal conductivity value in every run time, for whcih
up with the different thermal conductivity value in every run time, for which
it behaves like randomly.
- RTA thermal conductivity with smearing method (`--sigma`) is made to run with
@ -466,7 +508,7 @@ loader.
## Apr-16-2016: version 1.10.7
- API example is prepared and it is found in `Si` example. No doucment yet.
- API example is prepared and it is found in `Si` example. No documentation yet.
- Si pwscf example was placed in `example-phono3py` directory.
- User interface bug fix.
@ -478,10 +520,10 @@ loader.
to phonopy-1.10.4.
- Python3 support
- For the RTA thermal conductivity calculation mode with using the linear
tetrahedron method, only necessary part of phonon-phonon interaction strengh
among phonons. This improves lifetime calculation performance, but as the
drawback, averaged ph-ph interaction strength can not be given. See
{ref}`full_pp_option`.
tetrahedron method, only necessary part of phonon-phonon interaction strength
among phonons is calculated. This improves lifetime calculation performance,
but as the drawback, averaged ph-ph interaction strength can not be given.
See {ref}`full_pp_option`.
- Pwscf interface ({ref}`calculator_interfaces`)
## Oct-10-2015: version 0.9.14
@ -578,7 +620,7 @@ loader.
## Changes in version 0.8.0
- `--q_direction` didn't work. Fix it.
- Implementation of tetrahedron method whcih is activated by `--thm`.
- Implementation of tetrahedron method which is activated by `--thm`.
- Grid addresses are written out by `--wgp` option.
## Changes in version 0.7.6
@ -592,8 +634,9 @@ loader.
that needed for creating fc3 if index permutation symmetry is considered.
Therefore using index permutation symmetry, some elements of fc3 can be
recovered even if some of supercell force calculations are missing. In
paticular, all pair distances among triplet atoms are larger than cutoff pair
distance, any fc3 elements are not recovered, i.e., the element will be zero.
particular, all pair distances among triplet atoms are larger than cutoff
pair distance, any fc3 elements are not recovered, i.e., the element will be
zero.
## Changes in version 0.7.2

View File

@ -197,7 +197,6 @@ created from `FORCES_FC2` and `phono3py_disp.yaml` instead of `FORCES_FC3` and
```
(sp_option)=
### `--sp` or `--save-params`
Instead of `FORCES_FC3`, `phono3py_params.yaml` is generated. This option must
@ -329,16 +328,15 @@ information about primitive cell (`primitive_matrix` key) in
```
(random_displacements_option)=
### `--rd` (`RANDOM_DISPLACEMENTS`), `--rd-fc2` (`RANDOM_DISPLACEMENTS_FC2`) and `--random-seed` (`RANDOM_SEED`)
**`phono3py-load` doesn't have this option.**
See also {ref}`random-displacements`.
Random directional displacements are generated for fc3 and fc2 supercells by
`--rd` and `--rd-fc2`, respectively. `--amplitude` and `--random-seed` options
may be used together. These are used in the equivalent way to [`--rd` of
`--rd` and `--rd-fc2`, respectively. `--rd auto` can estimate a possible number
of supercells required (see {ref}`rd_number_estimation_factor_option`).
`--amplitude` and `--random-seed` options may be used together. These are used
in the equivalent way to [`--rd` of
phonopy](https://phonopy.github.io/phonopy/setting-tags.html#random-displacements).
Like `-d` option, it is recommended to specify `--pa auto` together with `--rd`
@ -348,6 +346,15 @@ and/or `--rd-fc2`,
% phono3py -c POSCAR-unitcell --dim 2 2 2 --dim-fc2 4 4 4 --rd 100 --rd-fc2 2 --pa auto
```
(rd_number_estimation_factor_option)=
### `--rd-auto-factor` (`RD_NUMBER_ESTIMATION_FACTOR`)
This scales the number of supercells generated by `--rd auto` by the specified
factor.
See
[RD_NUMBER_ESTIMATION_FACTOR](https://phonopy.github.io/phonopy/setting-tags.html#rd-number-estimation-factor).
(amplitude_option)=
### `--amplitude` (`DISPLACEMENT_DISTANCE`)
@ -377,7 +384,7 @@ To use different force constants calculators for fc2 and fc3
% phono3py-load --fc-calc "symfc|" ...
```
Those for fc2 and fc3 are seprated by `|` such as `symfc|` . Blank means to
Those for fc2 and fc3 are separated by `|` such as `symfc|` . Blank means to
employ the finite difference method for systematic displacements generated by
the option `-d`.
@ -596,7 +603,7 @@ expected.
### `--sigma` (`SIGMA`)
$\sigma$ value of Gaussian function for smearing when calculating imaginary part
of self energy. See the detail at {ref}`brillouinzone_sum`.
of self energy.
Multiple $\sigma$ values are also specified by space separated numerical values.
This is used when we want to test several $\sigma$ values simultaneously.
@ -721,7 +728,7 @@ out, i.e., `gamma` is still imaginary part of self energy of ph-ph scattering.
A most simple phonon boundary scattering treatment is included. $v_g/L$ is just
used as the scattering rate, where $v_g$ is the group velocity and $L$ is the
boundary mean free path. The value is given in micrometre. The default value, 1
boundary mean free path. The value is given in micrometer. The default value, 1
metre, is just used to avoid divergence of phonon lifetime and the contribution
to the thermal conductivity is considered negligible.
@ -760,8 +767,8 @@ where the averaged phonon-phonon interaction that is read from
`kappa-mxxx(-sx-sdx).hdf5` file is used if it exists in the file. Therefore the
averaged phonon-phonon interaction has to be stored before using this option
(see {ref}`--full-pp <full_pp_option>`). The calculation result **overwrites**
`kappa-mxxx(-sx-sdx).hdf5` file. Therefore to use this option together with `-o`
option is strongly recommended.
`kappa-mxxx(-sx-sdx).hdf5` file. Therefore the original
`kappa-mxxx(-sx-sdx).hdf5` file should be backed up.
First, run full conductivity calculation,
@ -804,50 +811,10 @@ $\Gamma^\text{U}_\lambda(\omega_\lambda)$ processes. The sum of them is usual
$\Gamma_\lambda(\omega_\lambda) =
\Gamma^\text{N}_\lambda(\omega_\lambda) +
\Gamma^\text{U}_\lambda(\omega_\lambda)$
and this is used to calcualte thermal conductivity in single-mode RTA. The
and this is used to calculate thermal conductivity in single-mode RTA. The
separation, i.e., the choice of G-vector, is made based on the first Brillouin
zone.
zone. See {ref}`iofile_kappa_hdf5_gamma_NU`.
The data are stored in `kappa-mxxx(-gx-sx-sdx).hdf5` file and accessed by
`gamma_N` and `gamma_U` keys. The shape of the arrays is the same as that of
`gamma` (see {ref}`kappa_hdf5_file_gamma`). An example (Si-PBEsol) is shown
below:
```bash
% phono3py-load --mesh 11 11 11 --fc3 --fc2 --br --nu
...
% ipython
In [1]: import h5py
In [2]: f = h5py.File("kappa-m111111.hdf5", 'r')
In [3]: list(f)
Out[3]:
['frequency',
'gamma',
'gamma_N',
'gamma_U',
'group_velocity',
'gv_by_gv',
'heat_capacity',
'kappa',
'kappa_unit_conversion',
'mesh',
'mode_kappa',
'qpoint',
'temperature',
'weight']
In [4]: f['gamma'].shape
Out[4]: (101, 56, 6)
In [5]: f['gamma_N'].shape
Out[5]: (101, 56, 6)
In [6]: f['gamma_U'].shape
Out[6]: (101, 56, 6)
```
### `--scattering-event-class` (`SCATTERING_EVENT_CLASS`)
@ -1051,7 +1018,7 @@ See also {ref}`reference papers <spectral_function_reference>`.
Spectral function of self energy $A_\lambda(\omega)$ is calculated with respect
to frequency $\omega$, where $\omega$ is sampled following
{ref}`freq_sampling_option`. First, imaginary part of self-energy is calculated
and then the real part is calculatd using the KramersKronig relation. The
and then the real part is calculated using the KramersKronig relation. The
output of $A_\lambda(\omega)$ is written to `spectral-mxxx-gx(-sx)-tx-bx.dat` in
THz (without $2\pi$) with respect to samplied frequency points of $\omega$ in
THz (without $2\pi$), and `spectral-mxxx-gx.hdf5`.
@ -1202,68 +1169,9 @@ not found, `kappa-mxxx-gx-bx(-sx-sdx).hdf5` files for band indices are searched.
### `--write-gamma-detail` (`WRITE_GAMMA_DETAIL = .TRUE.`)
Each q-point triplet contribution to imaginary part of self energy is written
into `gamma_detail-mxxx-gx(-sx-sdx).hdf5` file. Be careful that this is large
data.
into `gamma_detail-mxxx-gx(-sx-sdx).hdf5` file. Be careful that this can be a
large file. See {ref}`iofile_gamma_detail_hdf5`.
In the output file in hdf5, following keys are used to extract the detailed
information.
```{table}
| dataset | Array shape |
|-----------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
| gamma_detail for `--ise` | (temperature, sampling frequency point, symmetry reduced set of triplets at a grid point, band1, band2, band3) in THz (without $2\pi$) |
| gamma_detail for `--br` | (temperature, symmetry reduced set of triplets at a grid point, band1, band2, band3) in THz (without $2\pi$) |
| mesh | Numbers of sampling mesh along reciprocal axes. |
| frequency_point for `--ise` | Sampling frequency points in THz (without $2\pi$), i.e., $\omega$ in $\Gamma_\lambda(\omega)$ |
| temperature | (temperature,), Temperatures in K |
| triplet | (symmetry reduced set of triplets at a grid point, 3), Triplets are given by the grid point indices (see below). |
| weight | (symmetry reduced set of triplets at a grid point,), Weight of each triplet to imaginary part of self energy |
```
Imaginary part of self energy (linewidth/2) is recovered by the following
script:
```python
import h5py
import numpy as np
gd = h5py.File("gamma_detail-mxxx-gx.hdf5")
temp_index = 30 # index of temperature
temperature = gd['temperature'][temp_index]
gamma_tp = gd['gamma_detail'][:].sum(axis=-1).sum(axis=-1)
weight = gd['weight'][:]
gamma = np.dot(weight, gamma_tp[temp_index])
```
For example, for `--br`, this `gamma` gives $\Gamma_\lambda(\omega_\lambda)$ of
the band indices at the grid point indicated by $\lambda$ at the temperature of
index 30. If any bands are degenerated, those `gamma` in
`kappa-mxxx-gx(-sx-sdx).hdf5` or `gamma-mxxx-gx(-sx-sdx).hdf5` type file are
averaged, but the `gamma` obtained here in this way are not symmetrized. Apart
from this symmetrization, the values must be equivalent between them.
To understand each contribution of triptle to imaginary part of self energy,
reading `phonon-mxxx.hdf5` is useful (see {ref}`write_phonon_option`). For
example, phonon triplets of three phonon scatterings are obtained by
```python
import h5py
import numpy as np
gd = h5py.File("gamma_detail-mxxx-gx.hdf5", 'r')
ph = h5py.File("phonon-mxxx.hdf5", 'r')
gp1 = gd['grid_point'][()]
triplets = gd['triplet'][:] # Sets of (gp1, gp2, gp3) where gp1 is fixed
mesh = gd['mesh'][:]
grid_address = ph['grid_address'][:]
q_triplets = grid_address[triplets] / mesh.astype('double')
# Phonons of triplets[2]
phonon_tp = [(ph['frequency'][i], ph['eigenvector'][i]) for i in triplets[2]]
# Fractions of contributions of tripltes at this grid point and temperture index 30
gamma_sum_over_bands = np.dot(weight, gd['gamma_detail'][30].sum(axis=-1).sum(axis=-1).sum(axis=-1))
contrib_tp = [gd['gamma_detail'][30, i].sum() / gamma_sum_over_bands for i in range(len(weight))]
np.dot(weight, contrib_tp) # is one
```
(write_phonon_option)=
@ -1271,45 +1179,12 @@ np.dot(weight, contrib_tp) # is one
Phonon frequencies, eigenvectors, and grid point addresses are stored in
`phonon-mxxx.hdf5` file. {ref}`--pa <pa_option>` and {ref}`--nac <nac_option>`
may be required depending on calculation setting.
may be required depending on calculation setting. See {ref}`iofile_phonon_hdf5`.
```bash
% phono3py-load --mesh 11 11 11 --nac --write-phoonon
```
Contents of `phonon-mxxx.hdf5` are watched by:
```bash
In [1]: import h5py
In [2]: ph = h5py.File("phonon-m111111.hdf5", 'r')
In [3]: list(ph)
Out[3]: ['eigenvector', 'frequency', 'grid_address', 'mesh']
In [4]: ph['mesh'][:]
Out[4]: array([11, 11, 11], dtype=int32)
In [5]: ph['grid_address'].shape
Out[5]: (1367, 3)
In [6]: ph['frequency'].shape
Out[6]: (1367, 6)
In [7]: ph['eigenvector'].shape
Out[7]: (1367, 6, 6)
```
The first axis of `ph['grid_address']`, `ph['frequency']`, and
`ph['eigenvector']` corresponds to the number of q-points where phonons are
calculated. Here the number of phonons may not be equal to product of mesh
numbers ($1367 \neq 11^3$). This is because all q-points on Brillouin zone
boundary are included, i.e., even if multiple q-points are translationally
equivalent, those phonons are stored separately though these phonons are
physically equivalent within the equations employed in phono3py. Here Brillouin
zone is defined by WignerSeitz cell of reciprocal primitive basis vectors. This
is convenient to categorize phonon triplets into Umklapp and Normal scatterings
based on the Brillouin zone.
(read_phonon_option)=
@ -1358,10 +1233,6 @@ set. Other filters (`lzf` or integer values of 0 to 9) may be used, see h5py
documentation
(<http://docs.h5py.org/en/stable/high/dataset.html#filter-pipeline>).
### `-o`, `-i`, `--io`
These options are deprecated.
<!-- (output_filename_option)=
### `-o` (command option only)

View File

@ -58,9 +58,9 @@ copyright = "2015, Atsushi Togo"
# built documents.
#
# The short X.Y version.
version = "3.12"
version = "3.18"
# The full version, including alpha/beta/rc tags.
release = "3.12.2"
release = "3.18.0"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@ -142,7 +142,7 @@ pygments_style = "sphinx"
# # Allow a separate homepage from the master_doc
# "homepage": "index",
# # Allow the project link to be overriden to a custom URL.
# # Allow the project link to be overridden to a custom URL.
# "projectlink": "http://myproject.url",
# # Visible levels of the global TOC; -1 means unlimited

View File

@ -25,7 +25,7 @@ In phono3py, to obtain supercell-fc3,
$\Phi_{\alpha\beta\gamma}(jl, j'l', j''l'')$, forces in many
supercells having different pairs of displaced atoms are computed
using some force-calculator such as ab-initio code. In the phono3py
default behaviour, full elements of supercell-fc3 are computed. In
default behavior, full elements of supercell-fc3 are computed. In
this case, though depending on the number of atoms in the supercell
and the crystal symmetry, the number of atomic-pair configuration can
be huge and beyond our computational resource.

View File

@ -253,10 +253,10 @@ contained.
:width: 50%
:name: coleigplot
Eigenvalues are plotted in log scale (Si-PBEsol exmaple with
Eigenvalues are plotted in log scale (Si-PBEsol example with
15x15x15 mesh). The number in x-axis is just the index where each
eigenvalue is stored. Normally the eigenvalues are stored ascending
order. The bule points show the positive values, and
order. The blue points show the positive values, and
the red points show the negative values as positive values
(absolute values) to be able to plot in log scale. In this plot, we
can see the gap between $10^{-4}$ and $10^{-16}$, which

303
doc/grid.md Normal file
View File

@ -0,0 +1,303 @@
(grid)=
# Grids in reciprocal space
The regular grid can be a conventional regular grid or a generalized regular
grid. Here the conventional regular grid means that the grids are cut parallel
to the reciprocal basis vectors. In most cases, the conventional regular grid is
used. In special case, e.g., for crystals with body center tetragonal symmetry,
the generalized regular grid can be useful. In phono3py, the generalized regular
grid is defined to be cut parallel to the reciprocal basis vectors of the
conventional unit cell.
Two types of grid data structure are used in phono3py. Normal regular grid
contains translationally unique grid points (regular grid). The other grid
includes the points on Brillouin zone (BZ) boundary (BZ grid).
## `BZGrid` class instance
Grid point information in reciprocal space is stored in the `BZGrid` class. This
class instance can be easily accessed in the following way.
```python
In [1]: import phono3py
In [2]: ph3 = phono3py.load("phono3py.yaml", produce_fc=False)
In [3]: ph3.mesh_numbers = [11, 11, 11]
In [4]: ph3.grid
Out[4]: <phono3py.phonon.grid.BZGrid at 0x1070f3b60>
```
It is recommended to read docstring in `BZGrid` by
```python
In [5]: help(ph3.grid)
```
Some attributes of this class are presented below.
```python
In [6]: ph3.grid.addresses.shape
Out[6]: (1367, 3)
In [7]: ph3.grid.D_diag
Out[7]: array([11, 11, 11])
In [8]: ph3.grid.P
Out[8]:
array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
In [9]: ph3.grid.Q
Out[9]:
array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
In [10]: ph3.grid.QDinv
Out[10]:
array([[0.09090909, 0. , 0. ],
[0. , 0.09090909, 0. ],
[0. , 0. , 0.09090909]])
In [11]: ph3.grid.PS
Out[11]: array([0, 0, 0])
```
The integer array `addresses` contains grid point addresses. Every grid point
address is represented by the unique series of three integers. These addresses
are converted to the q-points in fractional coordinates as explained in the
{ref}`section below<grid_address_to_q>`.
Unless generalized regular grid is employed, the other attributes are not
important. `D_diag` is equivalent to the three integer numbers of the specified
conventional regular grid. `P` and `Q` are are the left and right unimodular
matrix after Smith normal form: $\mathrm{D}=\mathrm{PAQ}$, respectively, where
$\mathrm{A}$ is the grid matrix. `D_diag` is the three diagonal elements of the
matrix $\mathrm{D}$. The grid matrix is usually a diagonal matrix, then
$\mathrm{P}$ and $\mathrm{Q}$ are chosen as identity matrix. `QDinv` is given
by $\mathrm{Q}\mathrm{D}^{-1}$. `PS` represents half-grid-shifts (usually always
`[0, 0, 0]` in phono3py).
## Find grid point index corresponding to grid point address
Grid point index corresponding to a grid point address is obtained using the
instance method `BZGrid.get_indices_from_addresses` as follows:
```python
In [1]: import phono3py
In [2]: ph3 = phono3py.load("phono3py_disp.yaml")
In [3]: ph3.mesh_numbers = [20, 20, 20]
In [4]: ph3.grid.get_indices_from_addresses([0, 10, 10])
Out[4]: 4448
```
This index number is different between phono3py version 1.x and 2.x.
To get the number corresponding to the phono3py version 1.x,
`store_dense_gp_map=False` should be specified in `phono3py.load`,
```python
In [5]: ph3 = phono3py.load("phono3py_disp.yaml", store_dense_gp_map=False)
In [6]: ph3.mesh_numbers = [20, 20, 20]
In [7]: ph3.grid.get_indices_from_addresses([0, 10, 10])
Out[7]: 4200
```
(grid_address_to_q)=
## q-points in fractional coordinates corresponding to grid addresses
For Gamma centered regular grid, q-points in fractional coordinates
are obtained by
```python
qpoints = addresses @ QDinv.T
```
For shifted regular grid (usually unused in phono3py),
```python
qpoints = (addresses * 2 + PS) @ (QDinv.T / 2.0)
```
The grid addresses are stored in `phonon-*.hdf5`. So for conventional
Gamma-centered regular grid, those information can be used to recover the
corresponding q-points. For example,
```python
In [1]: import h5py
In [2]: f = h5py.File("phonon-m111111.hdf5")
In [3]: import numpy as np
In [8]: f['grid_address'][:] @ np.diag(1.0 / f['mesh'][:])
Out[8]:
array([[ 0. , 0. , 0. ],
[ 0.09090909, 0. , 0. ],
[ 0.18181818, 0. , 0. ],
...,
[-0.27272727, -0.09090909, -0.09090909],
[-0.18181818, -0.09090909, -0.09090909],
[-0.09090909, -0.09090909, -0.09090909]], shape=(1367, 3))
```
(grid_triplets)=
## Grid point triplets
Three grid point indices are used to represent a q-point triplet. For example
the following command generates `gamma_detail-m111111-g5.hdf5`,
```bash
% phono3py-load phono3py.yaml --gp 5 --br --mesh 11 11 11 --write-gamma-detail
```
This file contains various information:
```python
In [1]: import h5py
In [2]: f = h5py.File("gamma_detail-m111111-g5.hdf5")
In [3]: list(f)
Out[3]:
['gamma_detail',
'grid_point',
'mesh',
'temperature',
'triplet',
'triplet_all',
'version',
'weight']
In [4]: f['gamma_detail'].shape
Out[4]: (101, 146, 6, 6, 6)
```
For the detailed analysis of contributions of triplets to imaginary part of
self energy a phonon mode of the grid point, it is necessary to understand the
data structure of `triplet` and `weight`.
```python
In [5]: f['triplet'].shape
Out[5]: (146, 3)
In [6]: f['weight'].shape
Out[6]: (146,)
In [7]: f['triplet'][:10]
Out[7]:
array([[ 5, 0, 6],
[ 5, 1, 5],
[ 5, 2, 4],
[ 5, 3, 3],
[ 5, 7, 10],
[ 5, 8, 9],
[ 5, 11, 118],
[ 5, 12, 117],
[ 5, 13, 116],
[ 5, 14, 115]])
```
The second index of `gamma_detail` corresponds to the first index of `triplet`.
Three integers of each triplet are the grid point indices, which means, the grid
addresses and their q-points are recovered by
```python
In [8]: import phono3py
In [9]: ph3 = phono3py.load("phono3py.yaml", produce_fc=False)
In [10]: ph3.mesh_numbers = [11, 11, 11]
In [11]: ph3.grid.addresses[f['triplet'][:10]]
Out[11]:
array([[[ 5, 0, 0],
[ 0, 0, 0],
[-5, 0, 0]],
[[ 5, 0, 0],
[ 1, 0, 0],
[ 5, 0, 0]],
[[ 5, 0, 0],
[ 2, 0, 0],
[ 4, 0, 0]],
[[ 5, 0, 0],
[ 3, 0, 0],
[ 3, 0, 0]],
[[ 5, 0, 0],
[-4, 0, 0],
[-1, 0, 0]],
[[ 5, 0, 0],
[-3, 0, 0],
[-2, 0, 0]],
[[ 5, 0, 0],
[ 0, 1, 0],
[-5, -1, 0]],
[[ 5, 0, 0],
[ 1, 1, 0],
[ 5, -1, 0]],
[[ 5, 0, 0],
[ 2, 1, 0],
[ 4, -1, 0]],
[[ 5, 0, 0],
[ 3, 1, 0],
[ 3, -1, 0]]])
n [14]: ph3.grid.addresses[f['triplet'][:10]] @ ph3.grid.QDinv
Out[14]:
array([[[ 0.45454545, 0. , 0. ],
[ 0. , 0. , 0. ],
[-0.45454545, 0. , 0. ]],
[[ 0.45454545, 0. , 0. ],
[ 0.09090909, 0. , 0. ],
[ 0.45454545, 0. , 0. ]],
[[ 0.45454545, 0. , 0. ],
[ 0.18181818, 0. , 0. ],
[ 0.36363636, 0. , 0. ]],
[[ 0.45454545, 0. , 0. ],
[ 0.27272727, 0. , 0. ],
[ 0.27272727, 0. , 0. ]],
[[ 0.45454545, 0. , 0. ],
[-0.36363636, 0. , 0. ],
[-0.09090909, 0. , 0. ]],
[[ 0.45454545, 0. , 0. ],
[-0.27272727, 0. , 0. ],
[-0.18181818, 0. , 0. ]],
[[ 0.45454545, 0. , 0. ],
[ 0. , 0.09090909, 0. ],
[-0.45454545, -0.09090909, 0. ]],
[[ 0.45454545, 0. , 0. ],
[ 0.09090909, 0.09090909, 0. ],
[ 0.45454545, -0.09090909, 0. ]],
[[ 0.45454545, 0. , 0. ],
[ 0.18181818, 0.09090909, 0. ],
[ 0.36363636, -0.09090909, 0. ]],
[[ 0.45454545, 0. , 0. ],
[ 0.27272727, 0.09090909, 0. ],
[ 0.27272727, -0.09090909, 0. ]]])
```

View File

@ -1,23 +1,18 @@
(hdf5_howto)=
# How to read the results stored in hdf5 files
# Using phono3py hdf5 files
```{contents}
:depth: 3
:local:
```
## Using `h5py` in ipython
## How to use HDF5 python library
It is assumed that `python-h5py` is installed on the computer you interactively
use. In the following, how to see the contents of `.hdf5` files in the
interactive mode of Python. The basic usage of reading `.hdf5` files using
`h5py` is found at
[here](http://docs.h5py.org/en/latest/high/dataset.html#reading-writing-data>).
In the following example, an MgO result of thermal conductivity calculation
stored in `kappa-m111111.hdf5` (see {ref}`iofile_kappa_hdf5`) is loaded and
thermal conductivity tensor at 300 K is watched.
It is assumed that `python-h5py` is installed on the computer you
interactively use. In the following, how to see the contents of
`.hdf5` files in the interactive mode of Python. The basic usage of
reading `.hdf5` files using `h5py` is found at [here](http://docs.h5py.org/en/latest/high/dataset.html#reading-writing-data>).
Usually for running interactive python, `ipython` is recommended to
use but not the plain python. In the following example, an MgO result
of thermal conductivity calculation is loaded and thermal conductivity
tensor at 300 K is watched.
```bash
```python
In [1]: import h5py
In [2]: f = h5py.File("kappa-m111111.hdf5")
@ -90,256 +85,3 @@ In [11]: g = np.where(g > 0, g, -1)
In [12]: lifetime = np.where(g > 0, 1.0 / (2 * 2 * np.pi * g), 0)
```
(kappa_hdf5_file)=
## Details of `kappa-*.hdf5` file
Files name, e.g. `kappa-m323220.hdf5`, is determined by some
specific options. `mxxx`, show the numbers of sampling
mesh. `sxxx` and `gxxx` appear optionally. `sxxx` gives the
smearing width in the smearing method for Brillouin zone integration
for phonon lifetime, and `gxxx` denotes the grid number. Using the
command option of `-o`, the file name can be modified slightly. For
example `-o nac` gives `kappa-m323220.nac.hdf5` to
memorize the option `--nac` was used.
Currently `kappa-*.hdf5` file (not for the specific grid points)
contains the properties shown below.
### mesh
(Versions 1.10.11 or later)
The numbers of mesh points for reciprocal space sampling along
reciprocal axes, $a^*, b^*, c^*$.
### frequency
Phonon frequencies. The physical unit is THz, where THz
is in the ordinal frequency not the angular frequency.
The array shape is (irreducible q-point, phonon band).
(kappa_hdf5_file_gamma)=
### gamma
Imaginary part of self energy of phonon bubble diagram (phonon-phonon
scattering). The physical unit is THz, where THz is in the ordinal frequency not
the angular frequency.
The array shape for all grid-points (irreducible q-points) is
(temperature, irreducible q-point, phonon band).
The array shape for a specific grid-point is
(temperature, phonon band).
Phonon lifetime ($\tau_\lambda=1/2\Gamma_\lambda(\omega_\lambda)$) may
be estimated from `gamma`. $2\pi$ has to be multiplied with
`gamma` values in the hdf5 file to convert the unit of ordinal
frequency to angular frequency. Zeros in `gamma` values mean that
those elements were not calculated such as for three acoustic modes at
$\Gamma$ point. The below is the copy-and-paste from the
previous section to show how to obtain phonon lifetime in pico
second:
```bash
In [8]: g = f['gamma'][30]
In [9]: import numpy as np
In [10]: g = np.where(g > 0, g, -1)
In [11]: lifetime = np.where(g > 0, 1.0 / (2 * 2 * np.pi * g), 0)
```
### gamma_isotope
Isotope scattering of $1/2\tau^\mathrm{iso}_\lambda$.
The physical unit is same as that of gamma.
The array shape is same as that of frequency.
### group_velocity
Phonon group velocity, $\nabla_\mathbf{q}\omega_\lambda$. The
physical unit is $\text{THz}\cdot\text{Angstrom}$, where THz
is in the ordinal frequency not the angular frequency.
The array shape is (irreducible q-point, phonon band, 3 = Cartesian coordinates).
### heat_capacity
Mode-heat-capacity defined by
$$
C_\lambda = k_\mathrm{B}
\left(\frac{\hbar\omega_\lambda}{k_\mathrm{B} T} \right)^2
\frac{\exp(\hbar\omega_\lambda/k_\mathrm{B}
T)}{[\exp(\hbar\omega_\lambda/k_\mathrm{B} T)-1]^2}.
$$
The physical unit is eV/K.
The array shape is (temperature, irreducible q-point, phonon band).
(output_kappa)=
### kappa
Thermal conductivity tensor. The physical unit is W/m-K.
The array shape is (temperature, 6 = (xx, yy, zz, yz, xz, xy)).
(output_mode_kappa)=
### mode-kappa
Thermal conductivity tensors at k-stars (${}^*\mathbf{k}$):
$$
\sum_{\mathbf{q} \in {}^*\mathbf{k}} \kappa_{\mathbf{q}j}.
$$
The sum of this over ${}^*\mathbf{k}$ corresponding to
irreducible q-points divided by number of grid points gives
$\kappa$ ({ref}`output_kappa`), e.g.,:
```python
kappa_xx_at_index_30 = mode_kappa[30, :, :, 0].sum()/ weight.sum()
```
Be careful that until version 1.12.7, mode-kappa values were divided
by number of grid points.
The physical unit is W/m-K. Each tensor element is the sum of tensor
elements on the members of ${}^*\mathbf{k}$, i.e., symmetrically
equivalent q-points by crystallographic point group and time reversal
symmetry.
The array shape is (temperature, irreducible q-point, phonon band, 6 =
(xx, yy, zz, yz, xz, xy)).
### gv_by_gv
Outer products of group velocities for k-stars
(${}^*\mathbf{k}$) for each irreducible q-point and phonon band
($j$):
$$
\sum_{\mathbf{q} \in {}^*\mathbf{k}} \mathbf{v}_{\mathbf{q}j} \otimes
\mathbf{v}_{\mathbf{q}j}.
$$
The physical unit is
$\text{THz}^2\cdot\text{Angstrom}^2$, where THz is in the
ordinal frequency not the angular frequency.
The array shape is (irreducible q-point, phonon band, 6 = (xx, yy, zz,
yz, xz, xy)).
### q-point
Irreducible q-points in reduced coordinates.
The array shape is (irreducible q-point, 3 = reduced
coordinates in reciprocal space).
### temperature
Temperatures where thermal conductivities are calculated. The physical
unit is K.
### weight
Weights corresponding to irreducible q-points. Sum of weights equals to
the number of mesh grid points.
### ave_pp
Averaged phonon-phonon interaction in $\text{eV}^2,
$P_{\mathbf{q}j}$:
$$
P_{\mathbf{q}j} = \frac{1}{(3n_\mathrm{a})^2} \sum_{\lambda'\lambda''}
|\Phi_{\lambda\lambda'\lambda''}|^2.
$$
This is not going to be calculated in the RTA thermal coductivity
calculation mode by default. To calculate this, `--full-pp` option
has to be specified (see {ref}`full_pp_option`).
### boundary_mfp
A value specified by {ref}`boundary_mfp_option`. The physical unit is
micrometre.
When `--boundary-mfp` option is explicitly specified, its value is stored here.
### kappa_unit_conversion
This is used to convert the physical unit of lattice thermal
conductivity made of `heat_capacity`, `group_velocity`, and
`gamma`, to W/m-K. In the single mode relaxation time (SMRT) method,
a mode contribution to the lattice thermal conductivity is given by
$$
\kappa_\lambda = \frac{1}{V_0} C_\lambda \mathbf{v}_\lambda \otimes
\mathbf{v}_\lambda \tau_\lambda^{\mathrm{SMRT}}.
$$
For example, $\kappa_{\lambda,{xx}}$ is calculated by:
```bash
In [1]: import h5py
In [2]: f = h5py.File("kappa-m111111.hdf5")
In [3]: kappa_unit_conversion = f['kappa_unit_conversion'][()]
In [4]: weight = f['weight'][:]
In [5]: heat_capacity = f['heat_capacity'][:]
In [6]: gv_by_gv = f['gv_by_gv'][:]
In [7]: gamma = f['gamma'][:]
In [8]: kappa_unit_conversion * heat_capacity[30, 2, 0] * gv_by_gv[2, 0] / (2 * gamma[30, 2, 0])
Out[8]:
array([ 1.02050241e+03, 1.02050241e+03, 1.02050241e+03,
4.40486382e-15, 0.00000000e+00, -4.40486382e-15])
In [9]: f['mode_kappa'][30, 2, 0]
Out[9]:
array([ 1.02050201e+03, 1.02050201e+03, 1.02050201e+03,
4.40486209e-15, 0.00000000e+00, -4.40486209e-15])
```
## How to know grid point index number corresponding to grid address
Runngin with `--write-gamma`, hdf5 files are written out with file names
such as `kappa-m202020-g4448.hdf5`. You may want to know the grid point
index number with given grid address. This is done as follows:
```bash
In [1]: import phono3py
In [2]: ph3 = phono3py.load("phono3py_disp.yaml")
In [3]: ph3.mesh_numbers = [20, 20, 20]
In [4]: ph3.grid.get_indices_from_addresses([0, 10, 10])
Out[4]: 4448
```
This index number is different between phono3py version 1.x and 2.x.
To get the number corresponding to the phono3py version 1.x,
`store_dense_gp_map=False` should be specified in `phono3py.load`,
```bash
In [5]: ph3 = phono3py.load("phono3py_disp.yaml", store_dense_gp_map=False)
In [6]: ph3.mesh_numbers = [20, 20, 20]
In [7]: ph3.grid.get_indices_from_addresses([0, 10, 10])
Out[7]: 4200
```

View File

@ -6,7 +6,7 @@ the supercell approach. For example, the following physical values are obtained:
- {ref}`Lattice thermal conductivity by relaxation time approximation
and direct-solution of phonon Boltzmann equation and
the Wigner transport equation <LTC_options>`
- {ref}`Cummulative lattice thermal conductivity and related properties <auxiliary_tools_kaccum>`
- {ref}`Cumulative lattice thermal conductivity and related properties <auxiliary_tools_kaccum>`
- {ref}`self_energy_options` (Phonon lifetime/linewidth)
- {ref}`jdos_option`
- {ref}`spectral_function_option`
@ -38,7 +38,6 @@ examples
Interfaces to calculators (VASP, QE, CRYSTAL, Abinit, TURBOMOLE) <interfaces>
command-options
input-output-files
hdf5_howto
auxiliary-tools
direct-solution
wigner-solution
@ -49,7 +48,8 @@ cutoff-pair
external-tools
phono3py-api
phono3py-load
tips
hdf5_howto
grid
citation
reference
changelog

View File

@ -2,34 +2,30 @@
# Input / Output files
```{contents}
:depth: 3
:local:
```
The calculation results are written into files. Mostly the data are stored in
HDF5 format, therefore how to read the data from HDF5 files is also shown.
## Intermediate text files
The following files are not compatible with phonopy. But phonopy's `FORCE_SETS`
file can be created using phono3py command options from the following files. See
the detail at {ref}`file_format_compatibility`.
### `phono3py_disp.yaml`
This is created with `-d` option. See {ref}`create_displacements_option`.
## `phono3py_disp.yaml`
This is created with {ref}`-d <create_displacements_option>` or
{ref}`--rd <random_displacements_option>` option.
This file contains displacement dataset and crystal structure information.
Parameters for non-analytical term correction can be also included.
(input-output_files_FORCES_FC3)=
## `phono3py_params.yaml`
### `FORCES_FC3`
This is created with `--cf3` option. See {ref}`cf3_option`.
This is created with the combination of {ref}`--cf3 <cf3_option>` and {ref}`--sp
<sp_option>` options. This file contains displacement-force dataset and crystal
structure information. In addition, energies of supercells may be included in
the dataset. Parameters for non-analytical term correction can be also included.
There are two formats of `FORCES_FC3`. The type-I format is like that shown
below
(iofile_FORCES_FC3)=
## `FORCES_FC3`
This is created with {ref}`--cf3 <cf3_option>` option . There are two formats of
`FORCES_FC3`. The type-I format is like that shown below
```
# File: 1
@ -79,22 +75,13 @@ The type-II format is the same as
[phonopy's type-II format](https://phonopy.github.io/phonopy/input-files.html#type-2)
of `FORCE_SETS`.
### `FORCES_FC2`
## `FORCES_FC2`
This is created with `--cf2` option. See {ref}`cf2_option` and
{ref}`dim_fc2_option`.
This is created with {ref}`--cf2 <dim_fc2_option>` option. The file formats
(type-I and type-II) are same as those of `FORCES_FC3`.
The file formats (type-I and type-II) are same as those of `FORCES_FC3`.
## HDF5 files
### `kappa-*.hdf5`
See the detail at {ref}`kappa_hdf5_file`.
(fc3_hdf5_file)=
### `fc3.hdf5`
(iofile_fc3_hdf5)=
## `fc3.hdf5`
Third order force constants (in real space) are stored in
$\mathrm{eV}/\text{Angstrom}^3$.
@ -145,9 +132,8 @@ $$
So what you have to set is `--pa="0 1/4 1/4 1/4 0 1/4 1/4 1/4 0"`.
(fc2_hdf5_file)=
### `fc2.hdf5`
(iofile_fc2_hdf5)=
## `fc2.hdf5`
Second order force constants are stored in $\mathrm{eV}/\text{Angstrom}^2$.
@ -159,29 +145,434 @@ in the shape of:
```
against $\Phi_{\alpha\beta}(l\kappa, l'\kappa')$. More detail is similar to the
case for {ref}`fc3_hdf5_file`.
case for {ref}`iofile_fc3_hdf5`.
### `gamma-*.hdf5`
(iofile_kappa_hdf5)=
## `kappa-*.hdf5`
Files name, e.g. `kappa-m323220.hdf5`, is determined by some
specific options. `mxxx`, show the numbers of sampling
mesh. `sxxx` and `gxxx` appear optionally. `sxxx` gives the
smearing width in the smearing method for Brillouin zone integration
for phonon lifetime, and `gxxx` denotes the grid number. Using the
command option of `-o`, the file name can be modified slightly. For
example `-o nac` gives `kappa-m323220.nac.hdf5` to
memorize the option `--nac` was used.
### `mesh`
(Versions 1.10.11 or later)
The numbers of mesh points for reciprocal space sampling along
reciprocal axes, $a^*, b^*, c^*$.
### `frequency`
Phonon frequencies. The physical unit is THz, where THz
is in the ordinal frequency not the angular frequency.
The array shape is (irreducible q-point, phonon band).
(iofile_kappa_hdf5_gamma)=
### `gamma`
Imaginary part of self energy of phonon bubble diagram (phonon-phonon
scattering). The physical unit is THz, where THz is in the ordinal frequency not
the angular frequency.
The array shape for all grid-points (irreducible q-points) is
(temperature, irreducible q-point, phonon band).
The array shape for a specific grid-point is
(temperature, phonon band).
Phonon lifetime ($\tau_\lambda=1/2\Gamma_\lambda(\omega_\lambda)$) may
be estimated from `gamma`. $2\pi$ has to be multiplied with
`gamma` values in the hdf5 file to convert the unit of ordinal
frequency to angular frequency. Zeros in `gamma` values mean that
those elements were not calculated such as for three acoustic modes at
$\Gamma$ point. The below is the copy-and-paste from the
previous section to show how to obtain phonon lifetime in pico
second:
```python
In [8]: g = f['gamma'][30]
In [9]: import numpy as np
In [10]: g = np.where(g > 0, g, -1)
In [11]: lifetime = np.where(g > 0, 1.0 / (2 * 2 * np.pi * g), 0)
```
### `gamma_isotope`
Isotope scattering of $1/2\tau^\mathrm{iso}_\lambda$.
The physical unit is same as that of gamma.
The array shape is same as that of frequency.
### `group_velocity`
Phonon group velocity, $\nabla_\mathbf{q}\omega_\lambda$. The
physical unit is $\text{THz}\cdot\text{Angstrom}$, where THz
is in the ordinal frequency not the angular frequency.
The array shape is (irreducible q-point, phonon band, 3 = Cartesian coordinates).
### `heat_capacity`
Mode-heat-capacity defined by
$$
C_\lambda = k_\mathrm{B}
\left(\frac{\hbar\omega_\lambda}{k_\mathrm{B} T} \right)^2
\frac{\exp(\hbar\omega_\lambda/k_\mathrm{B}
T)}{[\exp(\hbar\omega_\lambda/k_\mathrm{B} T)-1]^2}.
$$
The physical unit is eV/K.
The array shape is (temperature, irreducible q-point, phonon band).
(iofile_kappa_hdf5_kappa)=
### `kappa`
Thermal conductivity tensor. The physical unit is W/m-K.
The array shape is (temperature, 6 = (xx, yy, zz, yz, xz, xy)).
### `mode-kappa`
Thermal conductivity tensors at k-stars (${}^*\mathbf{k}$):
$$
\sum_{\mathbf{q} \in {}^*\mathbf{k}} \kappa_{\mathbf{q}j}.
$$
The sum of this over ${}^*\mathbf{k}$ corresponding to
irreducible q-points divided by number of grid points gives
$\kappa$ ({ref}`iofile_kappa_hdf5_kappa`), e.g.,:
```python
kappa_xx_at_index_30 = mode_kappa[30, :, :, 0].sum()/ weight.sum()
```
Be careful that until version 1.12.7, mode-kappa values were divided
by number of grid points.
The physical unit is W/m-K. Each tensor element is the sum of tensor
elements on the members of ${}^*\mathbf{k}$, i.e., symmetrically
equivalent q-points by crystallographic point group and time reversal
symmetry.
The array shape is (temperature, irreducible q-point, phonon band, 6 =
(xx, yy, zz, yz, xz, xy)).
### `gv_by_gv`
Outer products of group velocities for k-stars
(${}^*\mathbf{k}$) for each irreducible q-point and phonon band
($j$):
$$
\sum_{\mathbf{q} \in {}^*\mathbf{k}} \mathbf{v}_{\mathbf{q}j} \otimes
\mathbf{v}_{\mathbf{q}j}.
$$
The physical unit is
$\text{THz}^2\cdot\text{Angstrom}^2$, where THz is in the
ordinal frequency not the angular frequency.
The array shape is (irreducible q-point, phonon band, 6 = (xx, yy, zz,
yz, xz, xy)).
### `q-point`
Irreducible q-points in reduced coordinates.
The array shape is (irreducible q-point, 3 = reduced
coordinates in reciprocal space).
### `temperature`
Temperatures where thermal conductivities are calculated. The physical
unit is K.
### `weight`
Weights corresponding to irreducible q-points. Sum of weights equals to
the number of mesh grid points.
### `ave_pp`
Averaged phonon-phonon interaction $P_{\mathbf{q}j}$ in $\text{eV}^2$:
$$
P_{\mathbf{q}j} = \frac{1}{(3n_\mathrm{a})^2} \sum_{\lambda'\lambda''}
|\Phi_{\lambda\lambda'\lambda''}|^2.
$$
This is not going to be calculated in the RTA thermal coductivity
calculation mode by default. To calculate this, `--full-pp` option
has to be specified (see {ref}`full_pp_option`).
### `boundary_mfp`
A value specified by {ref}`boundary_mfp_option`. The physical unit is
micrometer.
When `--boundary-mfp` option is explicitly specified, its value is stored here.
### `kappa_unit_conversion`
This is used to convert the physical unit of lattice thermal
conductivity made of `heat_capacity`, `group_velocity`, and
`gamma`, to W/m-K. In the single mode relaxation time (SMRT) method,
a mode contribution to the lattice thermal conductivity is given by
$$
\kappa_\lambda = \frac{1}{V_0} C_\lambda \mathbf{v}_\lambda \otimes
\mathbf{v}_\lambda \tau_\lambda^{\mathrm{SMRT}}.
$$
For example, $\kappa_{\lambda,{xx}}$ is calculated by:
```python
In [1]: import h5py
In [2]: f = h5py.File("kappa-m111111.hdf5")
In [3]: kappa_unit_conversion = f['kappa_unit_conversion'][()]
In [4]: weight = f['weight'][:]
In [5]: heat_capacity = f['heat_capacity'][:]
In [6]: gv_by_gv = f['gv_by_gv'][:]
In [7]: gamma = f['gamma'][:]
In [8]: kappa_unit_conversion * heat_capacity[30, 2, 0] * gv_by_gv[2, 0] / (2 * gamma[30, 2, 0])
Out[8]:
array([ 1.02050241e+03, 1.02050241e+03, 1.02050241e+03,
4.40486382e-15, 0.00000000e+00, -4.40486382e-15])
In [9]: f['mode_kappa'][30, 2, 0]
Out[9]:
array([ 1.02050201e+03, 1.02050201e+03, 1.02050201e+03,
4.40486209e-15, 0.00000000e+00, -4.40486209e-15])
```
(iofile_kappa_hdf5_gamma_NU)=
### `gamma_N` and `gamma_U`
The data are stored in `kappa-mxxx(-gx-sx-sdx).hdf5` file and accessed by
`gamma_N` and `gamma_U` keys. The shape of the arrays is the same as that of
`gamma` (see {ref}`iofile_kappa_hdf5_gamma`). An example (Si-PBEsol) is shown
below:
```bash
% phono3py-load --mesh 11 11 11 --fc3 --fc2 --br --nu
...
% ipython
```
```python
In [1]: import h5py
In [2]: f = h5py.File("kappa-m111111.hdf5", 'r')
In [3]: list(f)
Out[3]:
['frequency',
'gamma',
'gamma_N',
'gamma_U',
'group_velocity',
'gv_by_gv',
'heat_capacity',
'kappa',
'kappa_unit_conversion',
'mesh',
'mode_kappa',
'qpoint',
'temperature',
'weight']
In [4]: f['gamma'].shape
Out[4]: (101, 56, 6)
In [5]: f['gamma_N'].shape
Out[5]: (101, 56, 6)
In [6]: f['gamma_U'].shape
Out[6]: (101, 56, 6)
```
## `gamma-*.hdf5`
Imaginary parts of self energies at harmonic phonon frequencies
($\Gamma_\lambda(\omega_\lambda)$ = half linewidths) are stored in THz. See
{ref}`write_gamma_option`.
### `gamma_detail-*.hdf5`
(iofile_gamma_detail_hdf5)=
## `gamma_detail-*.hdf5`
Q-point triplet contributions to imaginary parts of self energies at phonon
frequencies (half linewidths) are stored in THz. See
{ref}`write_detailed_gamma_option`.
{ref}`--write-gamma-detail <write_detailed_gamma_option>` option.
## Simple text file
In the output file in hdf5, following keys are used to extract the detailed
information.
### `gammas-*.dat`
```{table}
| dataset | Array shape |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| gamma_detail for `--ise` | (temperature, sampling frequency point, symmetry reduced set of triplets at given grid point, band1, band2, band3) in THz (without $2\pi$) |
| gamma_detail for `--br` | (temperature, symmetry reduced set of triplets at gvien grid point, band1, band2, band3) in THz (without $2\pi$) |
| mesh | Numbers of sampling mesh along reciprocal axes. |
| frequency_point for `--ise` | Sampling frequency points in THz (without $2\pi$), i.e., $\omega$ in $\Gamma_\lambda(\omega)$ |
| temperature | (temperature,), Temperatures in K |
| triplet | (symmetry reduced set of triplets at given grid point, 3), Triplets are given by the grid point indices (see below). |
| weight | (symmetry reduced set of triplets at given grid point,), Weight of each triplet to imaginary part of self energy |
| triplet_all | (triplets at given grid point, 3), symmetry non-reduced version of the triplet information. |
```
See {ref}`grid_triplets` to recover the q-points of each triplet.
Imaginary part of self energy (linewidth/2) is recovered by the following
script:
```python
import h5py
import numpy as np
gd = h5py.File("gamma_detail-mxxx-gx.hdf5")
temp_index = 30 # index of temperature
temperature = gd['temperature'][temp_index]
gamma_tp = gd['gamma_detail'][:].sum(axis=-1).sum(axis=-1)
weight = gd['weight'][:]
gamma = np.dot(weight, gamma_tp[temp_index])
```
For example, for `--br`, this `gamma` gives $\Gamma_\lambda(\omega_\lambda)$ of
the band indices at the grid point indicated by $\lambda$ at the temperature of
index 30. If any bands are degenerated, those `gamma` in
`kappa-mxxx-gx(-sx-sdx).hdf5` or `gamma-mxxx-gx(-sx-sdx).hdf5` type file are
averaged, but the `gamma` obtained here in this way are not symmetrized. Apart
from this symmetrization, the values must be equivalent between them.
To understand each contribution of triptle to imaginary part of self energy,
reading `phonon-mxxx.hdf5` is useful (see {ref}`write_phonon_option`). For
example, phonon triplets of three phonon scatterings are obtained by
```python
import h5py
import numpy as np
gd = h5py.File("gamma_detail-mxxx-gx.hdf5", 'r')
ph = h5py.File("phonon-mxxx.hdf5", 'r')
gp1 = gd['grid_point'][()]
triplets = gd['triplet'][:] # Sets of (gp1, gp2, gp3) where gp1 is fixed
mesh = gd['mesh'][:]
grid_address = ph['grid_address'][:]
q_triplets = grid_address[triplets] / mesh.astype('double') # For conventional regular grid
# Phonons of triplets[2]
phonon_tp = [(ph['frequency'][i], ph['eigenvector'][i]) for i in triplets[2]]
# Fractions of contributions of triplets at this grid point and temperature index 30
gamma_sum_over_bands = np.dot(weight, gd['gamma_detail'][30].sum(axis=-1).sum(axis=-1).sum(axis=-1))
contrib_tp = [gd['gamma_detail'][30, i].sum() / gamma_sum_over_bands for i in range(len(weight))]
np.dot(weight, contrib_tp) # is one
```
(iofile_phonon_hdf5)=
## `phonon-*.hdf5`
Contents of `phonon-mxxx.hdf5` are watched by:
```python
In [1]: import h5py
In [2]: f = h5py.File("phonon-m111111.hdf5")
In [3]: list(f)
Out[3]:
['eigenvector',
'frequency',
'grid_address',
'ir_grid_points',
'ir_grid_weights',
'mesh',
'version']
In [4]: f['mesh'][:]
Out[4]: array([11, 11, 11])
In [5]: f['grid_address'].shape
Out[5]: (1367, 3)
In [6]: f['frequency'].shape
Out[6]: (1367, 6)
In [7]: f['eigenvector'].shape
Out[7]: (1367, 6, 6)
In [8]: f['ir_grid_points'].shape
Out[8]: (56,)
```
The first axis of `ph['grid_address']`, `ph['frequency']`, and
`ph['eigenvector']` corresponds to the number of q-points where phonons are
calculated. Here the number of phonons may not be equal to product of mesh
numbers ($1367 \neq 11^3$). This is because all q-points on Brillouin zone
boundary are included, i.e., even if multiple q-points are translationally
equivalent, those phonons are stored separately though these phonons are
physically equivalent within the equations employed in phono3py. Here Brillouin
zone is defined by WignerSeitz cell of reciprocal primitive basis vectors. This
is convenient to categorize phonon triplets into Umklapp and Normal scatterings
based on the Brillouin zone.
## `pp-*.hdf5`
This file contains phonon-phonon interaction strength
$\bigl|\Phi_{\lambda\lambda'\lambda''}\bigl|^2$. To use the data in this
file, it is recommended to generate with `--full-pp` option because the data
structure to access becomes simpler.
```bash
% phono3py-load phono3py.yaml --gp 5 --br --mesh 11 11 11 --write-pp --full-pp
```
```python
In [1]: import h5py
In [2]: f = h5py.File("pp-m111111-g5.hdf5")
In [3]: list(f)
Out[3]: ['pp', 'triplet', 'triplet_all', 'version', 'weight']
In [4]: f['pp'].shape
Out[4]: (146, 6, 6, 6)
```
Indices of the `pp` array are (symmetry reduced set of triplets at given grid
point, band1, band2, band3), and the values are given in $\text{eV}^2$. See
{ref}`grid_triplets` to recover the q-points of each triplet.
Except for `pp`, all the other information are equivalent to those found in
{ref}`iofile_gamma_detail_hdf5`.
## `gammas-*.dat`
Imaginary parts of self energies with respect to frequency
$\Gamma_\lambda(\omega)$ are stored in THz. See {ref}`ise_option`.
### `jdos-*.dat`
## `jdos-*.dat`
Joint densities of states are stored in Thz. See {ref}`jdos_option`.
### `linewidth-*.dat`
## `linewidth-*.dat`

View File

@ -148,7 +148,7 @@ shape of `(num_supercells, num_atoms_in_supercell, 3)`. In the above example,
the array shape is `(1254, 72, 3)`.
If the calculated force sets are stored in the
{ref}`input-output_files_FORCES_FC3` file, the numpy array of `forces` is
{ref}`iofile_FORCES_FC3` file, the numpy array of `forces` is
obtained by
```python

View File

@ -9,7 +9,7 @@ over many different force calculators. Once `phono3py_disp.yaml` is created, the
following operations will be the same using this command.
This is used almost in the same way as `phono3py` command, e.g., but there are
some differences. The following default behaviours are different from that of
some differences. The following default behaviors are different from that of
those of `phono3py` command:
1. `phono3py_xxx.yaml` type file is always necessary in either of two ways:

View File

@ -2,8 +2,6 @@
# Force constants calculation using pypolymlp (machine learning potential)
**This is an experimental feature.**
With the `--pypolymlp` option, phono3py can interface with the polynomial
machine learning potential (MLP) code,
[pypolymlp](https://github.com/sekocha/pypolymlp), to perform training and
@ -20,8 +18,8 @@ For further details on combining phono3py calculations with pypolymlp, refer to
[[doi](https://doi.org/10.1063/5.0211296)]
[[arxiv](https://arxiv.org/abs/2401.17531)].
An example of its usage can be found in the `example/NaCl-pypolymlp` directory
in the distribution from GitHub or PyPI.
Examples of its usage can be found in the `example/NaCl-pypolymlp` and
`example/AlN-rd` directories in the distribution from GitHub or PyPI.
## Citation of pypolymlp
@ -61,7 +59,7 @@ in the distribution from GitHub or PyPI.
`phono3py_params.yaml`. Use {ref}`--cf3 <cf3_option>` and {ref}`--sp
<sp_option>` option simultaneously.
4. Develop MLPs. By default, 90 and 10 percents of the dataset are used for the
training and test, respectively. At this step `phono3py.pmlp` is saved.
training and test, respectively. At this step `polymlp.yaml` is saved.
5. Generate displacements in supercells either systematic or random displacements.
6. Evaluate MLPs for forces of the supercells generated in step 5.
7. Calculate force constants from displacement-force dataset from steps 5 and 6.
@ -153,28 +151,28 @@ obtained by
```
``````
### Step 4: Development of MLPs
The `phono3py_params.yaml` file contains the training data required for
developing polynomial MLPs when running with the `--pypolymlp` option.
```
% phono3py-load --pypolymlp phono3py_params.yaml
phono3py-load --pypolymlp phono3py_params.yaml
_ _____
_ __ | |__ ___ _ __ ___|___ / _ __ _ _
| '_ \| '_ \ / _ \| '_ \ / _ \ |_ \| '_ \| | | |
| |_) | | | | (_) | | | | (_) |__) | |_) | |_| |
| .__/|_| |_|\___/|_| |_|\___/____/| .__/ \__, |
|_| |_| |___/
3.11.3
3.18.0
-------------------------[time 2025-01-19 18:02:40]-------------------------
-------------------------[time 2025-07-26 13:59:10]-------------------------
Compiled with OpenMP support (max 10 threads).
Running in phono3py.load mode.
Python version 3.12.6
Spglib version 2.5.0
Python version 3.13.3
Spglib version 2.6.1
----------------------------- General settings -----------------------------
Run mode: pypolymlp
HDF5 data compression filter: gzip
Crystal structure was read from "phono3py_params.yaml".
Supercell (dim): [2 2 2]
@ -187,6 +185,7 @@ Use -v option to watch primitive cell, unit cell, and supercell structures.
NAC parameters were read from "phono3py_params.yaml".
Displacement dataset for fc3 was read from "phono3py_params.yaml".
----------------------------- pypolymlp start ------------------------------
Pypolymlp version 0.12.9
Pypolymlp is a generator of polynomial machine learning potentials.
Please cite the paper: A. Seko, J. Appl. Phys. 133, 011101 (2023).
Pypolymlp is developed at https://github.com/sekocha/pypolymlp.
@ -199,26 +198,11 @@ Parameters:
gaussian_params1: (1.0, 1.0, 1)
gaussian_params2: (0.0, 7.0, 10)
Developing MLPs by pypolymlp...
Regression: cholesky decomposition ...
- alpha: 0.001
- alpha: 0.01
- alpha: 0.1
- alpha: 1.0
- alpha: 10.0
Clear training X.T @ X
Calculate X.T @ X for test data
Clear test X.T @ X
Regression: model selection ...
- alpha = 1.000e-03 : rmse (train, test) = 1.12211e+15 1.12211e+15
- alpha = 1.000e-02 : rmse (train, test) = 1.12211e+15 1.12211e+15
- alpha = 1.000e-01 : rmse (train, test) = 0.00002 0.00002
- alpha = 1.000e+00 : rmse (train, test) = 0.00002 0.00002
- alpha = 1.000e+01 : rmse (train, test) = 0.00002 0.00002
MLPs were written into "phono3py.pmlp"
MLPs were written into "polymlp.yaml"
------------------------------ pypolymlp end -------------------------------
Generate displacements (--rd or -d) for proceeding to phonon calculations.
Summary of calculation was written in "phono3py.yaml".
-------------------------[time 2025-01-19 18:03:44]-------------------------
-------------------------[time 2025-07-26 14:00:12]-------------------------
_
___ _ __ __| |
/ _ \ '_ \ / _` |
@ -228,7 +212,7 @@ Summary of calculation was written in "phono3py.yaml".
Information about the development of MLPs using pypolymlp is provided between
the `pypolymlp start` and `pypolymlp end` sections. The polynomial MLPs are
saved in the `phono3py.pmlp` file, which can be reused in subsequent phono3py
saved in the `polymlp.yaml` file, which can be reused in subsequent phono3py
executions with the `--pypolymlp` option when only displacements (and no forces)
are provided.
@ -237,7 +221,7 @@ are provided.
With the `-d` option, displacements are systematically generated while taking
crystal symmetry into account. When running with the `--pypolymlp` option, MLPs
are read from `phono3py.pmlp` if the file exists. In this case, training data is
are read from `polymlp.yaml` if the file exists. In this case, training data is
no longer required, and files such as `phono3py.yaml` can be used as the input
structure file.
@ -249,14 +233,15 @@ structure file.
| |_) | | | | (_) | | | | (_) |__) | |_) | |_| |
| .__/|_| |_|\___/|_| |_|\___/____/| .__/ \__, |
|_| |_| |___/
3.11.3
3.18.0
-------------------------[time 2025-01-19 18:06:46]-------------------------
-------------------------[time 2025-07-26 14:00:49]-------------------------
Compiled with OpenMP support (max 10 threads).
Running in phono3py.load mode.
Python version 3.12.6
Spglib version 2.5.0
Python version 3.13.3
Spglib version 2.6.1
----------------------------- General settings -----------------------------
Run mode: pypolymlp + force constants
HDF5 data compression filter: gzip
Crystal structure was read from "phono3py.yaml".
Supercell (dim): [2 2 2]
@ -268,14 +253,16 @@ Spacegroup: Fm-3m (225)
Use -v option to watch primitive cell, unit cell, and supercell structures.
NAC parameters were read from "phono3py.yaml".
----------------------------- pypolymlp start ------------------------------
Pypolymlp version 0.12.9
Pypolymlp is a generator of polynomial machine learning potentials.
Please cite the paper: A. Seko, J. Appl. Phys. 133, 011101 (2023).
Pypolymlp is developed at https://github.com/sekocha/pypolymlp.
Load MLPs from "phono3py.pmlp".
Load MLPs from "polymlp.yaml".
------------------------------ pypolymlp end -------------------------------
Generate displacements
Displacement distance: 0.01
Evaluate forces in 292 supercells by pypolymlp
Dataset generated using MLPs was written in "phono3py_mlp_eval_dataset.yaml".
----------------------------- Force constants ------------------------------
Computing fc3[ 1, x, x ] using numpy.linalg.pinv.
Displacements (in Angstrom):
@ -286,16 +273,26 @@ Displacements (in Angstrom):
[ 0.0100 0.0000 0.0000]
[-0.0100 0.0000 0.0000]
Expanding fc3.
fc3 was symmetrized.
fc2 was symmetrized.
Max drift of fc3: 0.000000 (zzz) 0.000000 (zzz) 0.000000 (zzz)
Max drift of fc2: 0.000000 (zz) 0.000000 (zz)
Symmetrizing fc3 by symfc projector.
Symfc version 1.5.3 (https://github.com/symfc/symfc)
Citation: A. Seko and A. Togo, Phys. Rev. B, 110, 214302 (2024)
Symmetrizing fc2 by symfc projector.
Symfc version 1.5.3 (https://github.com/symfc/symfc)
Citation: A. Seko and A. Togo, Phys. Rev. B, 110, 214302 (2024)
Max drift of fc3: 0.00000000 (zyz) 0.00000000 (yzz) 0.00000000 (yzz)
Max drift of fc2: -0.00000000 (yy) -0.00000000 (yy)
fc3 was written into "fc3.hdf5".
fc2 was written into "fc2.hdf5".
--------------------------- Calculation settings ---------------------------
Non-analytical term correction (NAC): True
NAC unit conversion factor: 14.39965
BZ integration: Tetrahedron-method
Temperatures: 0.0 300.0
Cutoff frequency: 0.01
Frequency conversion factor to THz: 15.63330
----------- None of ph-ph interaction calculation was performed. -----------
Dataset generated using MLPs was written in "phono3py_mlp_eval_dataset.yaml".
Summary of calculation was written in "phono3py.yaml".
-------------------------[time 2025-01-19 18:06:55]-------------------------
-------------------------[time 2025-07-26 14:00:58]-------------------------
_
___ _ __ __| |
/ _ \ '_ \ / _` |
@ -312,29 +309,28 @@ corresponding forces are stored in the `phono3py_mlp_eval_dataset.yaml` file.
### Steps 5-7: Force constants calculation (random displacements in step 5)
Random displacements are generated by specifying {ref}`--rd
<random_displacements_option>` option. To compute force constants with random
displacements, an external force constants calculator is necessary. By default,
symfc is used unless another force constants solver is explicitly specified.
When running with the `--pypolymlp` option, MLPs are read from `phono3py.pmlp`
if the file exists. In this case, training data is no longer required, and files
such as `phono3py.yaml` can be used as the input structure file.
<random_displacements_option>` option. When running with the `--pypolymlp`
option, MLPs are read from `polymlp.yaml` if the file exists. In this case,
training data is no longer required, and files such as `phono3py.yaml` can be
used as the input structure file.
```
% phono3py-load --pypolymlp --rd 200 phono3py.yaml
% phono3py-load --pypolymlp --rd auto phono3py.yaml
_ _____
_ __ | |__ ___ _ __ ___|___ / _ __ _ _
| '_ \| '_ \ / _ \| '_ \ / _ \ |_ \| '_ \| | | |
| |_) | | | | (_) | | | | (_) |__) | |_) | |_| |
| .__/|_| |_|\___/|_| |_|\___/____/| .__/ \__, |
|_| |_| |___/
3.11.3
3.18.0
-------------------------[time 2025-01-19 18:13:21]-------------------------
-------------------------[time 2025-07-26 14:02:24]-------------------------
Compiled with OpenMP support (max 10 threads).
Running in phono3py.load mode.
Python version 3.12.6
Spglib version 2.5.0
Python version 3.13.3
Spglib version 2.6.1
----------------------------- General settings -----------------------------
Run mode: pypolymlp + force constants
HDF5 data compression filter: gzip
Crystal structure was read from "phono3py.yaml".
Supercell (dim): [2 2 2]
@ -346,39 +342,43 @@ Spacegroup: Fm-3m (225)
Use -v option to watch primitive cell, unit cell, and supercell structures.
NAC parameters were read from "phono3py.yaml".
----------------------------- pypolymlp start ------------------------------
Pypolymlp version 0.12.9
Pypolymlp is a generator of polynomial machine learning potentials.
Please cite the paper: A. Seko, J. Appl. Phys. 133, 011101 (2023).
Pypolymlp is developed at https://github.com/sekocha/pypolymlp.
Load MLPs from "phono3py.pmlp".
Load MLPs from "polymlp.yaml".
------------------------------ pypolymlp end -------------------------------
Generate random displacements
Twice of number of snapshots will be generated for plus-minus displacements.
Displacement distance: 0.01
Evaluate forces in 400 supercells by pypolymlp
Evaluate forces in 32 supercells by pypolymlp
Dataset generated using MLPs was written in "phono3py_mlp_eval_dataset.yaml".
----------------------------- Force constants ------------------------------
Symfc will be used to handle general (or random) displacements.
Type-II dataset for displacements and forces was provided,
but the selected force constants calculator cannot process it.
Use another force constants calculator, e.g., symfc,
to generate force constants.
Try symfc to handle general (or random) displacements.
-------------------------------- Symfc start -------------------------------
Symfc is a force constants calculator. See the following paper:
A. Seko and A. Togo, Phys. Rev. B, 110, 214302 (2024).
Symfc is developed at https://github.com/symfc/symfc.
Symfc version 1.5.3 (https://github.com/symfc/symfc)
Citation: A. Seko and A. Togo, Phys. Rev. B, 110, 214302 (2024)
Computing [2, 3] order force constants.
Increase log-level to watch detailed symfc log.
--------------------------------- Symfc end --------------------------------
-------------------------------- Symfc start -------------------------------
Symfc is a force constants calculator. See the following paper:
A. Seko and A. Togo, Phys. Rev. B, 110, 214302 (2024).
Symfc is developed at https://github.com/symfc/symfc.
Computing [2] order force constants.
Increase log-level to watch detailed symfc log.
--------------------------------- Symfc end --------------------------------
Max drift of fc3: -0.000000 (zxz) -0.000000 (xzz) -0.000000 (xzz)
Max drift of fc2: -0.000000 (yy) -0.000000 (yy)
Max drift of fc3: -0.00000000 (xyx) -0.00000000 (yxx) -0.00000000 (yxx)
Max drift of fc2: -0.00000000 (yy) -0.00000000 (yy)
fc3 was written into "fc3.hdf5".
fc2 was written into "fc2.hdf5".
--------------------------- Calculation settings ---------------------------
Non-analytical term correction (NAC): True
NAC unit conversion factor: 14.39965
BZ integration: Tetrahedron-method
Temperatures: 0.0 300.0
Cutoff frequency: 0.01
Frequency conversion factor to THz: 15.63330
----------- None of ph-ph interaction calculation was performed. -----------
Dataset generated using MLPs was written in "phono3py_mlp_eval_dataset.yaml".
Summary of calculation was written in "phono3py.yaml".
-------------------------[time 2025-01-19 18:13:34]-------------------------
-------------------------[time 2025-07-26 14:02:29]-------------------------
_
___ _ __ __| |
/ _ \ '_ \ / _` |
@ -386,88 +386,121 @@ Summary of calculation was written in "phono3py.yaml".
\___|_| |_|\__,_|
```
After the MLPs are read, 200 supercells with random directional displacements
are generated. These displacements are then inverted (such as $\Delta
\mathbf{u}_i$ and $-\Delta \mathbf{u}_i$ of all atoms $i$ in each supercell),
resulting in an additional 200 supercells. In total, 400 supercells are created.
The forces for these supercells are then evaluated. Finally, the force constants
are calculated using symfc.
After the MLPs are read, 16 supercells with random directional displacements are
generated by the option `--rd auto`. These displacements are then inverted (such
as $\Delta \mathbf{u}_i$ and $-\Delta \mathbf{u}_i$ of all atoms $i$ in each
supercell), resulting in an additional 16 supercells. In total, 32 supercells
are created. The forces for these supercells are then evaluated. Finally, the
force constants are calculated using symfc. The `--rd-auto-factor` option can
change the number of supercells generated.
### Command options for force constants calculation
## Command options for force constants calculation
After obtaining the MLPs, displacements are generated using those MLPs, and the
resulting forces are computed accordingly. The displacement distance is set by
the `--amplitude` option, whose default value is 0.01 Angstrom. When the `--rd`
option is used, it specifies the number of supercells with random directional
displacements. Note that to achieve accurate force constants, the actual number
of generated supercells is twice the specified number. If `--rd` is omitted,
systematic displacements are introduced.
After obtaining the MLPs, displacements are generated using these MLPs, and the
resulting forces are computed. The displacement distance is controlled by the
`--amplitude` option, with a default value of 0.01 Angstrom. When `-d` is
specified, systematic displacements are introduced. When the `--rd` option is
used, it specifies the number of supercells with random directional
displacements. To ensure accurate force constants, the actual number of
generated supercells is twice the specified value.
Once the file `phono3py.pmlp` is obtained, force constants can be calculated
using MLPs from `phono3py.pmlp`. After removing the `fc3.hdf5` and `fc2.hdf5`
files, `phono3py-load` will detect `phono3py.pmlp` and then compute the force
constants by loading the MLPs from `phono3py.pmlp` as follows:
When atoms in the unit cell have positional degrees of freedom within the
crystal symmetry, the `--relax-atomic-positions` option can relax their
positions using MLPs. In the `example/AlN-rd` case, the following command
develops polynomial MLPs and then relaxes atomic positions using these MLPs. The
force constants are calculated using supercells with 0.005 Angstrom systematic
displacements.
```
% phono3py-load --pypolymlp --rd 100 --amplitude 0.005 phono3py.yaml
% phono3py-load phonopy_params_mp-661.yaml.xz --pypolymlp --relax-atomic-positions -d
_ _____
_ __ | |__ ___ _ __ ___|___ / _ __ _ _
| '_ \| '_ \ / _ \| '_ \ / _ \ |_ \| '_ \| | | |
| |_) | | | | (_) | | | | (_) |__) | |_) | |_| |
| .__/|_| |_|\___/|_| |_|\___/____/| .__/ \__, |
|_| |_| |___/
3.11.3
3.18.0-dev21+ge26f3ecb
-------------------------[time 2025-01-19 18:19:02]-------------------------
-------------------------[time 2025-07-26 14:29:16]-------------------------
Compiled with OpenMP support (max 10 threads).
Running in phono3py.load mode.
Python version 3.12.6
Spglib version 2.5.0
Python version 3.13.3
Spglib version 2.6.1
----------------------------- General settings -----------------------------
Run mode: pypolymlp + force constants
HDF5 data compression filter: gzip
Crystal structure was read from "phono3py.yaml".
Supercell (dim): [2 2 2]
Crystal structure was read from "phonopy_params_mp-661.yaml.xz".
Supercell (dim): [4 4 2]
Primitive matrix:
[0. 0.5 0.5]
[0.5 0. 0.5]
[0.5 0.5 0. ]
Spacegroup: Fm-3m (225)
[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]
Spacegroup: P6_3mc (186)
Use -v option to watch primitive cell, unit cell, and supercell structures.
NAC parameters were read from "phono3py.yaml".
NAC parameters were read from "phonopy_params_mp-661.yaml.xz".
Displacement dataset for fc3 was read from "phonopy_params_mp-661.yaml.xz".
----------------------------- pypolymlp start ------------------------------
Pypolymlp version 0.12.9.post0
Pypolymlp is a generator of polynomial machine learning potentials.
Please cite the paper: A. Seko, J. Appl. Phys. 133, 011101 (2023).
Pypolymlp is developed at https://github.com/sekocha/pypolymlp.
Load MLPs from "phono3py.pmlp".
Parameters:
cutoff: 8.0
model_type: 3
max_p: 2
gtinv_order: 3
gtinv_maxl: (8, 8)
gaussian_params1: (1.0, 1.0, 1)
gaussian_params2: (0.0, 7.0, 10)
Developing MLPs by pypolymlp...
MLPs were written into "polymlp.yaml"
------------------------------ pypolymlp end -------------------------------
Generate random displacements
Twice of number of snapshots will be generated for plus-minus displacements.
Relaxing atomic positions using polynomial MLPs...
Change in fractional position and in distance:
1 N : 0.00000000 0.00000000 -0.00000021 (|d|=0.00000105)
2 N : 0.00000000 0.00000000 -0.00000021 (|d|=0.00000105)
3 Al: 0.00000000 0.00000000 0.00000021 (|d|=0.00000105)
4 Al: 0.00000000 0.00000000 0.00000021 (|d|=0.00000105)
----------------------------------------------------------------------------
Generate displacements
Displacement distance: 0.005
Evaluate forces in 200 supercells by pypolymlp
Evaluate forces in 3720 supercells by pypolymlp
Dataset generated using MLPs was written in "phono3py_mlp_eval_dataset.yaml".
----------------------------- Force constants ------------------------------
Symfc will be used to handle general (or random) displacements.
-------------------------------- Symfc start -------------------------------
Symfc is a force constants calculator. See the following paper:
A. Seko and A. Togo, Phys. Rev. B, 110, 214302 (2024).
Symfc is developed at https://github.com/symfc/symfc.
Computing [2, 3] order force constants.
Increase log-level to watch detailed symfc log.
--------------------------------- Symfc end --------------------------------
-------------------------------- Symfc start -------------------------------
Symfc is a force constants calculator. See the following paper:
A. Seko and A. Togo, Phys. Rev. B, 110, 214302 (2024).
Symfc is developed at https://github.com/symfc/symfc.
Computing [2] order force constants.
Increase log-level to watch detailed symfc log.
--------------------------------- Symfc end --------------------------------
Max drift of fc3: -0.000000 (zxz) -0.000000 (xzz) -0.000000 (xzz)
Max drift of fc2: -0.000000 (yy) -0.000000 (yy)
Computing fc3[ 1, x, x ] using numpy.linalg.pinv.
Displacements (in Angstrom):
[ 0.0050 0.0000 0.0000]
[-0.0050 0.0000 0.0000]
[ 0.0000 0.0000 0.0050]
[ 0.0000 0.0000 -0.0050]
Computing fc3[ 65, x, x ] using numpy.linalg.pinv.
Displacements (in Angstrom):
[ 0.0050 0.0000 0.0000]
[-0.0050 0.0000 0.0000]
[ 0.0000 0.0000 0.0050]
[ 0.0000 0.0000 -0.0050]
Expanding fc3.
Symmetrizing fc3 by symfc projector.
Symfc version 1.5.3 (https://github.com/symfc/symfc)
Citation: A. Seko and A. Togo, Phys. Rev. B, 110, 214302 (2024)
Symmetrizing fc2 by symfc projector.
Symfc version 1.5.3 (https://github.com/symfc/symfc)
Citation: A. Seko and A. Togo, Phys. Rev. B, 110, 214302 (2024)
Max drift of fc3: -0.00000000 (xxz) -0.00000000 (xxz) -0.00000000 (xzx)
Max drift of fc2: -0.00000000 (xx) -0.00000000 (xx)
fc3 was written into "fc3.hdf5".
fc2 was written into "fc2.hdf5".
--------------------------- Calculation settings ---------------------------
Non-analytical term correction (NAC): True
NAC unit conversion factor: 14.39965
BZ integration: Tetrahedron-method
Temperatures: 0.0 300.0
Cutoff frequency: 0.01
Frequency conversion factor to THz: 15.63330
----------- None of ph-ph interaction calculation was performed. -----------
Dataset generated using MLPs was written in "phono3py_mlp_eval_dataset.yaml".
Summary of calculation was written in "phono3py.yaml".
-------------------------[time 2025-01-19 18:19:09]-------------------------
-------------------------[time 2025-07-26 14:39:11]-------------------------
_
___ _ __ __| |
/ _ \ '_ \ / _` |
@ -475,7 +508,6 @@ Summary of calculation was written in "phono3py.yaml".
\___|_| |_|\__,_|
```
## Parameters for developing MLPs
A few parameters can be specified using the `--mlp-params` option for the
@ -539,3 +571,14 @@ the next 100 supercells) will be computed and included. With this procedure in
mind, it may be convenient to generate a sufficiently large number of supercells
with random displacements in advance, such as 1000 supercells, before starting
the LTC calculation with pypolymlp.
## Converting `phono3py.pmlp` to `polymlp.yaml`
In older versions, polynomial MLPs were stored in `phono3py.pmlp`. This file can
be converted to `polymlp.yaml` using the following Python snippet.
```python
from pypolymlp.mlp_dev.pypolymlp import Pypolymlp
polymlp = Pypolymlp()
polymlp.convert_to_yaml(filename_txt="phono3py.pmlp", filename_yaml="polymlp.yaml”)
```

View File

@ -22,7 +22,7 @@ The option `--rd NUM` is used instead of `-d` in generating displacements as fol
`NUM` means the number of supercells with random directional displacements. This
must be specified, and the initial guess may be from around the number of
supecells generated for the systematic displacements by `-d`. In the case of the
supercells generated for the systematic displacements by `-d`. In the case of the
`NaCl-rd` example, 146 supercells are generated with `-d`, so similar
number `--rd 100` was chosen here.

View File

@ -1,111 +0,0 @@
(tips)=
# Tips
```{contents}
:depth: 2
:local:
```
(brillouinzone_sum)=
## Brillouin zone summation
Brillouin zone (BZ) summations appear at different two points in
phonon lifetime calculation. First it is used for the Fourier
transform of force constants, and second to obtain imaginary part of
phonon-self-energy. For the summation, usually uniform sampling meshes
are employed. To obtain more accurate result, it is always better to
use denser meshes. But the denser mesh requires more computational
demand.
The second BZ summation contains delta functions. In
phono3py calculation, a linear tetrahedron method ({ref}`thm option <thm_option>`, default option) and a smearing method ({ref}`sigma option <sigma_option>`) can be used for this BZ
integration. In most cases, the tetrahedron method is better. Especially in high
thermal conductivity materials, the smearing method results in
underestimation of lattice thermal conductivity.
The figure below shows Si thermal conductivity convergence with
respect to number of mesh points along an axis from n=19 to 65. This
is calculated with RTA and the linear tetrahedron method. Within the
methods and phono3py implementation, it is converging at around n=55,
however this computational demand is not trivial. As far as observing
this result, an extrapolation to $1/n \rightarrow 0$ seems not a
good idea, since it gives overestimation in the case of this Si
example. This plot tells that we have to decide how much value is
acceptable as lattice thermal conductivity value. Therefore it
important to describe the number of sampling mesh and method of BZ
integration to let other people reproduce the computational results.
```{image} Si-convergence.png
:width: 25%
```
In case the smearing method is necessary to use, the convergence of
q-point mesh together with smearing width has to be checked
carefully. Since smearing parameter is used to approximate delta
functions, small `sigma` value is better to describe the detailed
structure of three-phonon-space, however it requires a denser sampling
mesh to converge the result. To check the convergence with respect to
the `sigma` value, multiple sigma values can be set. This can be
computationally efficient, since it is avoided to re-calculate
phonon-phonon interaction strength for different `sigma` values in
this case. Convergence with respect to the sampling mesh and smearing
parameter strongly depends on materials. For Si example, a
$20\times 20\times 20$ sampling mesh (or 8000 reducible sampling
points) and 0.1 THz smearing value for reciprocal of the volume of an
atom may be a good starting choice. The tetrahedron method requires no
such parameter as the smearing width.
## Importance of numerical quality of force constants
Third-order force constants (fc3) are much weaker to numerical noise
of a force calculator than second-order force constants
(fc2). Therefore supercell force calculations have to be done very
carefully.
Numerical quality of forces given by force calculators is the most
important factor for the numerical quality of lattice thermal
conductivity calculation. We may be able to apply symmetry constraints
to force constants, however even if force constants fulfill those
symmetries, the numerical quality of force constants is not guaranteed
since elements of force constants just suffice the symmetries but most
of those intensities are not constrained.
It is important to use the best possible force calculator in the
possibly best way. The knowledge of the force calculator from the
theory and method to the practical usage is required to obtain
good results of lattice thermal conductivity calculation.
In the following, a few things that may be good to know are
presented.
### A practical way to check lattice thermal conductivity result
Some feeling whether our calculation result is OK or not may be
obtained by comparing lattice thermal conductivities calculated with
and without {ref}`symmetrizations of force constants <symmetrization_option>`. If they are enough different, e.g., more
than twice different, it is better to re-consider about the force
calculation. In the case of DFT calculations, the choice of input
settings such as k-point sampling mesh, plane-wave energy cutoff, and
exchange-correlational potential, etc, should be reconsidered.
### Displacement distance of atoms
The phono3py default displacement distance is 0.03
$\text{Angstrom}$. In some cases, accurate result may not be obtained
due to the numerical noise of the force calculator. Usually increasing
the displacement distance by the {ref}`amplitude option <amplitude_option>` reduces the numerical noise, but as its drawback
higher order anharmonicity is involved (renormalized) into fc3 and fc2.
(file_format_compatibility)=
## File format compatibility with phonopy
- `FORCES_FC3` and `FORCES_FC2` are not
compatible with phonopy's `FORCE_SETS`.
- `FORCE_SETS` can be created using {ref}`--cfs <cfs_option>` from
`FORCES_FC3` and `phono3py_disp.yaml` or `FORCES_FC2` and
`phono3py_disp.yaml` (needs to specify `--dim-fc2`).
- `FORCES_FC2` can be created using {ref}`--fs2f2 <fs2f2_option>` from `FORCE_SETS`.
- `fc2.hdf5` can be used in phonopy in the `hdf5` mode when it is
renamed to `force_constants.hdf5`. In the previous combinations of
phonopy and phono3py, depending on the physical unit of force
constants of calculators, the direct compatibility is not guranteed.

63
example/AlN-rd/README.md Normal file
View File

@ -0,0 +1,63 @@
# AlN lattice thermal conductivity calculation from dataset for pypolymlp
## Computational setting of VASP calculations
For supercell forces and energies
- Supercell 4x4x2 of wurtzite unit cell
- Random directional displacements of 0.03 Angstrom
- PBE-sol
- 520 eV cutoff energy
- Gamma centered 2x2x2 kpoint mesh
- LREAL = .FALSE.
- ADDGRID = .TRUE.
For parameters of non-analytical term correction,
- PBE-sol
- 520 eV cutoff energy
- Gamma centered 7x7x4 kpoint mesh
- LEPSION = .TRUE.
- LREAL = .FALSE.
These data are stored in `phonopy_params_mp-661.yaml.xz`.
## Example of lattice thermal conductivity calculation
MLPs by pypolymlp are developed by
```bash
% phono3py-load phonopy_params_mp-661.yaml.xz --pypolymlp -v
```
Dataset with 180 supercells is used for training and 20 for the test. This
calculation will take 5-10 minutes depending on computer resource.
`pypolymlp.yaml` is made by this command.
Force constants are calculated by
```bash
% phono3py-load phonopy_params_mp-661.yaml.xz --pypolymlp --relax-atomic-positions -d
```
With the `--relax-atomic-positions` option, internal atomic positions in unit
cell are optimized by pypolymlp. The displacement-force dataset is stored in
`phono3py_mlp_eval_dataset.yaml`. Force constants are symmetried using symfc,
but the phono3py's traditional symmetrizer can be used with the option
`--fc-calculator traditional`. The symmetry constraints applied by this
traditional symmetrizer is weaker, but the calculation demands less memory
space.
Lattice thermal conductivity is calculated by
```bash
% phono3py-load phonopy_params_mp-661.yaml.xz --mesh 40 --br
```
Steps written above are performed in one-shot by
```bash
% phono3py-load phonopy_params_mp-661.yaml.xz --pypolymlp --relax-atomic-positions -d --mesh 40 --br
```
The lattice thermal conductivity calculated at 300 K will be around k_xx=252 and k_zz=232.

Binary file not shown.

View File

@ -1,6 +1,6 @@
This is the example of NaCl calculation. Since all atoms are displaced, to
obtain force constants, an external force constants calculator is necessary,
i.e., build-in force constants calculator has no ability to compute force
i.e., built-in force constants calculator has no ability to compute force
constants for such dataset. In this example, ALM is used. See
https://phonopy.github.io/phonopy/setting-tags.html#alm. The easiest way to
install ALM is to use conda.

View File

@ -0,0 +1,13 @@
import phonopy
import phono3py
ph3 = phono3py.load("phono3py_params_NaCl.yaml.xz", produce_fc=False, log_level=2)
ph = phonopy.Phonopy(
unitcell=ph3.unitcell,
supercell_matrix=ph3.phonon_supercell_matrix,
primitive_matrix=ph3.primitive_matrix,
)
ph.dataset = ph3.phonon_dataset
ph.nac_params = ph3.nac_params
ph.save("phonopy_params_NaCl.yaml")

View File

@ -34,8 +34,16 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from phono3py.api_isotope import Phono3pyIsotope # noqa F401
from phono3py.api_jointdos import Phono3pyJointDos # noqa F401
from phono3py.api_phono3py import Phono3py # noqa F401
from phono3py.cui.load import load # noqa F401
from phono3py.version import __version__ # noqa F401
from phono3py.api_isotope import Phono3pyIsotope
from phono3py.api_jointdos import Phono3pyJointDos
from phono3py.api_phono3py import Phono3py
from phono3py.cui.load import load
from phono3py.version import __version__
__all__ = [
"Phono3pyIsotope",
"Phono3pyJointDos",
"Phono3py",
"load",
"__version__",
]

View File

@ -35,9 +35,9 @@
# POSSIBILITY OF SUCH DAMAGE.
import numpy as np
from phonopy.units import VaspToTHz
from phono3py.other.isotope import Isotope
from phono3py.phonon.grid import BZGrid
class Phono3pyIsotope:
@ -50,7 +50,7 @@ class Phono3pyIsotope:
mass_variances=None, # length of list is num_atom.
band_indices=None,
sigmas=None,
frequency_factor_to_THz=VaspToTHz,
frequency_factor_to_THz=None,
use_grg=False,
symprec=1e-5,
cutoff_frequency=None,
@ -82,7 +82,7 @@ class Phono3pyIsotope:
return self._iso.dynamical_matrix
@property
def grid(self):
def grid(self) -> BZGrid:
"""Return BZGrid class instance."""
return self._iso.bz_grid

View File

@ -34,10 +34,13 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import annotations
import numpy as np
from phonopy.harmonic.dynamical_matrix import DynamicalMatrix
from phonopy.physical_units import get_physical_units
from phonopy.structure.cells import Primitive, Supercell
from phonopy.structure.symmetry import Symmetry
from phonopy.units import VaspToTHz
from phono3py.file_IO import write_joint_dos
from phono3py.phonon.grid import BZGrid
@ -65,7 +68,7 @@ class Phono3pyJointDos:
num_frequency_points=None,
num_points_in_batch=None,
temperatures=None,
frequency_factor_to_THz=VaspToTHz,
frequency_factor_to_THz=None,
frequency_scale_factor=None,
use_grg=False,
SNF_coordinates="reciprocal",
@ -87,7 +90,10 @@ class Phono3pyJointDos:
else:
self._sigmas = sigmas
self._cutoff_frequency = cutoff_frequency
self._frequency_factor_to_THz = frequency_factor_to_THz
if frequency_factor_to_THz is None:
self._frequency_factor_to_THz = get_physical_units().DefaultToTHz
else:
self._frequency_factor_to_THz = frequency_factor_to_THz
self._frequency_scale_factor = frequency_scale_factor
self._is_mesh_symmetry = is_mesh_symmetry
self._is_symmetry = is_symmetry
@ -113,7 +119,7 @@ class Phono3pyJointDos:
self.initialize(mesh)
@property
def grid(self):
def grid(self) -> BZGrid | None:
"""Return BZGrid class instance."""
return self._bz_grid
@ -267,7 +273,7 @@ class Phono3pyJointDos:
print("Smearing method with sigma=%s is used." % sigma)
print(
f"Calculations at {len(self._frequency_points)} "
f"frequency points are devided into {len(batches)} batches."
f"frequency points are divided into {len(batches)} batches."
)
for i_t, temperature in enumerate(temperatures):
self._jdos.temperature = temperature
@ -290,7 +296,7 @@ class Phono3pyJointDos:
print('JDOS is written into "%s".' % filename)
@property
def dynamical_matrix(self):
def dynamical_matrix(self) -> DynamicalMatrix:
"""Return DynamicalMatrix class instance."""
return self._jdos.dynamical_matrix

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,740 @@
"""Init lattice thermal conductivity classes with direct solution."""
# Copyright (C) 2020 Atsushi Togo
# All rights reserved.
#
# This file is part of phono3py.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# * Neither the name of the phonopy project nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import annotations
import os
import sys
from collections.abc import Sequence
from typing import Union
from numpy.typing import ArrayLike
from phono3py.conductivity.base import get_unit_to_WmK
from phono3py.conductivity.direct_solution import ConductivityLBTE
from phono3py.conductivity.direct_solution_base import ConductivityLBTEBase
from phono3py.conductivity.utils import (
select_colmat_solver,
write_pp_interaction,
)
from phono3py.conductivity.wigner_direct_solution import ConductivityWignerLBTE
from phono3py.file_IO import (
read_collision_from_hdf5,
write_collision_eigenvalues_to_hdf5,
write_collision_to_hdf5,
write_kappa_to_hdf5,
write_unitary_matrix_to_hdf5,
)
from phono3py.phonon3.interaction import Interaction, all_bands_exist
cond_LBTE_type = Union[ConductivityLBTE, ConductivityWignerLBTE]
def get_thermal_conductivity_LBTE(
interaction: Interaction,
temperatures: Sequence | None = None,
sigmas: Sequence | None = None,
sigma_cutoff: float | None = None,
is_isotope: bool = False,
mass_variances: Sequence | None = None,
grid_points: ArrayLike | None = None,
boundary_mfp: float | None = None, # in micrometer
solve_collective_phonon: bool = False,
is_reducible_collision_matrix: bool = False,
is_kappa_star: bool = True,
gv_delta_q: float | None = None,
is_full_pp: bool = False,
conductivity_type: str | None = None,
pinv_cutoff: float = 1.0e-8,
pinv_solver: int = 0, # default: dsyev in lapacke
pinv_method: int = 0, # default: abs(eig) < cutoff
write_collision: bool = False,
read_collision: str | Sequence | None = None,
write_kappa: bool = False,
write_pp: bool = False,
read_pp: bool = False,
write_LBTE_solution: bool = False,
compression: str = "gzip",
input_filename: str | os.PathLike | None = None,
output_filename: str | os.PathLike | None = None,
log_level: int = 0,
):
"""Calculate lattice thermal conductivity by direct solution."""
if temperatures is None:
_temperatures = [
300,
]
else:
_temperatures = temperatures
if sigmas is None:
sigmas = []
if log_level:
print("-" * 19 + " Lattice thermal conductivity (LBTE) " + "-" * 19)
print(
"Cutoff frequency of pseudo inversion of collision matrix: %s" % pinv_cutoff
)
if read_collision:
temps = None
else:
temps = _temperatures
if conductivity_type == "wigner":
conductivity_LBTE_class = ConductivityWignerLBTE
else:
conductivity_LBTE_class = ConductivityLBTE
lbte = conductivity_LBTE_class(
interaction,
grid_points=grid_points,
temperatures=temps,
sigmas=sigmas,
sigma_cutoff=sigma_cutoff,
is_isotope=is_isotope,
mass_variances=mass_variances,
boundary_mfp=boundary_mfp,
solve_collective_phonon=solve_collective_phonon,
is_reducible_collision_matrix=is_reducible_collision_matrix,
is_kappa_star=is_kappa_star,
gv_delta_q=gv_delta_q,
is_full_pp=is_full_pp,
read_pp=read_pp,
pp_filename=input_filename,
pinv_cutoff=pinv_cutoff,
pinv_solver=pinv_solver,
pinv_method=pinv_method,
log_level=log_level,
)
if read_collision:
read_from = _set_collision_from_file(
lbte,
indices=read_collision,
is_reducible_collision_matrix=is_reducible_collision_matrix,
filename=input_filename,
log_level=log_level,
)
if not read_from:
print("Reading collision failed.")
return False
if log_level:
temps_read = lbte.temperatures
if len(temps_read) > 5:
text = (" %.1f " * 5 + "...") % tuple(temps_read[:5])
text += " %.1f" % temps_read[-1]
else:
text = (" %.1f " * len(temps_read)) % tuple(temps_read)
print("Temperature: " + text)
# This computes pieces of collision matrix sequentially.
for i in lbte:
if write_pp:
write_pp_interaction(
lbte, interaction, i, filename=output_filename, compression=compression
)
if write_collision:
ConductivityLBTEWriter.write_collision(
lbte,
interaction,
i=i,
is_reducible_collision_matrix=is_reducible_collision_matrix,
is_one_gp_colmat=(grid_points is not None),
filename=output_filename,
)
lbte.delete_gp_collision_and_pp()
# Write full collision matrix
if write_LBTE_solution:
if (
read_collision
and all_bands_exist(interaction)
and read_from == "grid_points"
and grid_points is None
) or (not read_collision):
ConductivityLBTEWriter.write_collision(
lbte, interaction, filename=output_filename
)
if grid_points is None and all_bands_exist(interaction):
lbte.set_kappa_at_sigmas()
if write_kappa:
ConductivityLBTEWriter.write_kappa(
lbte,
interaction.primitive.volume,
is_reducible_collision_matrix=is_reducible_collision_matrix,
write_LBTE_solution=write_LBTE_solution,
pinv_solver=pinv_solver,
compression=compression,
filename=output_filename,
log_level=log_level,
)
return lbte
class ConductivityLBTEWriter:
"""Collection of result writers."""
@staticmethod
def write_collision(
lbte: cond_LBTE_type,
interaction: Interaction,
i=None,
is_reducible_collision_matrix=False,
is_one_gp_colmat=False,
filename=None,
):
"""Write collision matrix into hdf5 file."""
grid_points = lbte.grid_points
temperatures = lbte.temperatures
sigmas = lbte.sigmas
sigma_cutoff = lbte.sigma_cutoff_width
gamma = lbte.gamma
gamma_isotope = lbte.gamma_isotope
collision_matrix = lbte.collision_matrix
mesh = lbte.mesh_numbers
if i is not None:
gp = grid_points[i]
if is_one_gp_colmat:
igp = 0
else:
if is_reducible_collision_matrix:
igp = interaction.bz_grid.bzg2grg[gp]
else:
igp = i
if all_bands_exist(interaction):
for j, sigma in enumerate(sigmas):
if gamma_isotope is not None:
gamma_isotope_at_sigma = gamma_isotope[j, igp]
else:
gamma_isotope_at_sigma = None
write_collision_to_hdf5(
temperatures,
mesh,
gamma=gamma[j, :, igp],
gamma_isotope=gamma_isotope_at_sigma,
collision_matrix=collision_matrix[j, :, igp],
grid_point=gp,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
filename=filename,
)
else:
for j, sigma in enumerate(sigmas):
for k, bi in enumerate(interaction.band_indices):
if gamma_isotope is not None:
gamma_isotope_at_sigma = gamma_isotope[j, igp, k]
else:
gamma_isotope_at_sigma = None
write_collision_to_hdf5(
temperatures,
mesh,
gamma=gamma[j, :, igp, k],
gamma_isotope=gamma_isotope_at_sigma,
collision_matrix=collision_matrix[j, :, igp, k],
grid_point=gp,
band_index=bi,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
filename=filename,
)
else:
for j, sigma in enumerate(sigmas):
if gamma_isotope is not None:
gamma_isotope_at_sigma = gamma_isotope[j]
else:
gamma_isotope_at_sigma = None
write_collision_to_hdf5(
temperatures,
mesh,
gamma=gamma[j],
gamma_isotope=gamma_isotope_at_sigma,
collision_matrix=collision_matrix[j],
sigma=sigma,
sigma_cutoff=sigma_cutoff,
filename=filename,
)
@staticmethod
def write_kappa(
lbte: cond_LBTE_type,
volume: float,
is_reducible_collision_matrix: bool = False,
write_LBTE_solution: bool = False,
pinv_solver: int | None = None,
compression: str = "gzip",
filename: str | os.PathLike | None = None,
log_level: int = 0,
):
"""Write kappa related properties into a hdf5 file."""
if isinstance(lbte, ConductivityLBTE):
kappa = lbte.kappa
mode_kappa = lbte.mode_kappa
kappa_RTA = lbte.kappa_RTA
mode_kappa_RTA = lbte.mode_kappa_RTA
gv = lbte.group_velocities
gv_by_gv = lbte.gv_by_gv
else:
kappa = None
mode_kappa = None
kappa_RTA = None
mode_kappa_RTA = None
gv = None
gv_by_gv = None
if isinstance(lbte, ConductivityWignerLBTE):
kappa_P_exact = lbte.kappa_P_exact
kappa_P_RTA = lbte.kappa_P_RTA
kappa_C = lbte.kappa_C
mode_kappa_P_exact = lbte.mode_kappa_P_exact
mode_kappa_P_RTA = lbte.mode_kappa_P_RTA
mode_kappa_C = lbte.mode_kappa_C
else:
kappa_P_exact = None
kappa_P_RTA = None
kappa_C = None
mode_kappa_P_exact = None
mode_kappa_P_RTA = None
mode_kappa_C = None
temperatures = lbte.temperatures
sigmas = lbte.sigmas
sigma_cutoff = lbte.sigma_cutoff_width
mesh = lbte.mesh_numbers
bz_grid = lbte.bz_grid
grid_points = lbte.grid_points
weights = lbte.grid_weights
frequencies = lbte.frequencies
ave_pp = lbte.averaged_pp_interaction
qpoints = lbte.qpoints
gamma = lbte.gamma
gamma_isotope = lbte.gamma_isotope
f_vector = lbte.get_f_vectors()
mode_cv = lbte.mode_heat_capacities
mfp = lbte.get_mean_free_path()
boundary_mfp = lbte.boundary_mfp
coleigs = lbte.collision_eigenvalues
# After kappa calculation, the variable is overwritten by unitary matrix
unitary_matrix = lbte.collision_matrix
if is_reducible_collision_matrix:
frequencies = lbte.get_frequencies_all()
else:
frequencies = lbte.frequencies
for i, sigma in enumerate(sigmas):
if kappa is None:
kappa_at_sigma = None
else:
kappa_at_sigma = kappa[i]
if mode_kappa is None:
mode_kappa_at_sigma = None
else:
mode_kappa_at_sigma = mode_kappa[i]
if kappa_RTA is None:
kappa_RTA_at_sigma = None
else:
kappa_RTA_at_sigma = kappa_RTA[i]
if mode_kappa_RTA is None:
mode_kappa_RTA_at_sigma = None
else:
mode_kappa_RTA_at_sigma = mode_kappa_RTA[i]
if kappa_P_exact is None:
kappa_P_exact_at_sigma = None
else:
kappa_P_exact_at_sigma = kappa_P_exact[i]
if kappa_P_RTA is None:
kappa_P_RTA_at_sigma = None
else:
kappa_P_RTA_at_sigma = kappa_P_RTA[i]
if kappa_C is None:
kappa_C_at_sigma = None
else:
kappa_C_at_sigma = kappa_C[i]
if kappa_P_exact_at_sigma is None or kappa_C_at_sigma is None:
kappa_TOT_exact_at_sigma = None
else:
kappa_TOT_exact_at_sigma = kappa_P_exact_at_sigma + kappa_C_at_sigma
if kappa_P_RTA_at_sigma is None or kappa_C_at_sigma is None:
kappa_TOT_RTA_at_sigma = None
else:
kappa_TOT_RTA_at_sigma = kappa_P_RTA_at_sigma + kappa_C_at_sigma
if mode_kappa_P_exact is None:
mode_kappa_P_exact_at_sigma = None
else:
mode_kappa_P_exact_at_sigma = mode_kappa_P_exact[i]
if mode_kappa_P_RTA is None:
mode_kappa_P_RTA_at_sigma = None
else:
mode_kappa_P_RTA_at_sigma = mode_kappa_P_RTA[i]
if mode_kappa_C is None:
mode_kappa_C_at_sigma = None
else:
mode_kappa_C_at_sigma = mode_kappa_C[i]
if gamma_isotope is None:
gamma_isotope_at_sigma = None
else:
gamma_isotope_at_sigma = gamma_isotope[i]
write_kappa_to_hdf5(
temperatures,
mesh,
boundary_mfp=boundary_mfp,
bz_grid=bz_grid,
frequency=frequencies,
group_velocity=gv,
gv_by_gv=gv_by_gv,
mean_free_path=mfp[i],
heat_capacity=mode_cv,
kappa=kappa_at_sigma,
mode_kappa=mode_kappa_at_sigma,
kappa_RTA=kappa_RTA_at_sigma,
mode_kappa_RTA=mode_kappa_RTA_at_sigma,
kappa_P_exact=kappa_P_exact_at_sigma,
kappa_P_RTA=kappa_P_RTA_at_sigma,
kappa_C=kappa_C_at_sigma,
kappa_TOT_exact=kappa_TOT_exact_at_sigma,
kappa_TOT_RTA=kappa_TOT_RTA_at_sigma,
mode_kappa_P_exact=mode_kappa_P_exact_at_sigma,
mode_kappa_P_RTA=mode_kappa_P_RTA_at_sigma,
mode_kappa_C=mode_kappa_C_at_sigma,
f_vector=f_vector,
gamma=gamma[i],
gamma_isotope=gamma_isotope_at_sigma,
averaged_pp_interaction=ave_pp,
qpoint=qpoints,
grid_point=grid_points,
weight=weights,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
kappa_unit_conversion=get_unit_to_WmK() / volume,
compression=compression,
filename=filename,
verbose=log_level,
)
if coleigs is not None:
write_collision_eigenvalues_to_hdf5(
temperatures,
mesh,
coleigs[i],
sigma=sigma,
sigma_cutoff=sigma_cutoff,
filename=filename,
verbose=log_level,
)
if write_LBTE_solution:
if pinv_solver is not None:
solver = select_colmat_solver(pinv_solver)
if solver in [1, 2, 3, 4, 5]:
write_unitary_matrix_to_hdf5(
temperatures,
mesh,
unitary_matrix=unitary_matrix,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
solver=solver,
filename=filename,
verbose=log_level,
)
def _set_collision_from_file(
lbte: ConductivityLBTEBase,
indices: str | Sequence | None = "all",
is_reducible_collision_matrix=False,
filename=None,
log_level=0,
):
"""Set collision matrix from that read from files.
If collision-m*.hdf5 that contains all data is not found,
collision-m*-gp*.hdf5 files at grid points are searched. If any of those
files are not found, collision-m*-gp*-b*.hdf5 files at grid points and bands
are searched. If any of those files are not found, it fails.
lbte : ConductivityLBTEBase
RTA lattice thermal conductivity instance.
filename : str, optional
This string is inserted in the filename as collision-m*.{filename}.hdf5.
verbose : bool, optional
Show text output or not.
"""
bz_grid = lbte.bz_grid
sigmas = lbte.sigmas
sigma_cutoff = lbte.sigma_cutoff_width
mesh = lbte.mesh_numbers
grid_points = lbte.grid_points
read_from = None
if log_level:
print(
"---------------------- Reading collision data from file "
"----------------------",
flush=True,
)
arrays_allocated = False
for i_sigma, sigma in enumerate(sigmas):
collisions = read_collision_from_hdf5(
mesh,
indices=indices,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
filename=filename,
verbose=(log_level > 0),
)
if log_level:
sys.stdout.flush()
if collisions:
(colmat_at_sigma, gamma_at_sigma, temperatures) = collisions
if not arrays_allocated:
arrays_allocated = True
# The following invokes self._allocate_values()
lbte.temperatures = temperatures
lbte.collision_matrix[i_sigma] = colmat_at_sigma[0]
lbte.gamma[i_sigma] = gamma_at_sigma[0]
read_from = "full_matrix"
else:
vals = _allocate_collision(
True,
mesh,
sigma,
sigma_cutoff,
grid_points,
indices,
filename,
)
if vals:
colmat_at_sigma, gamma_at_sigma, temperatures = vals
else:
if log_level:
print("Collision at grid point %d doesn't exist." % grid_points[0])
vals = _allocate_collision(
False,
mesh,
sigma,
sigma_cutoff,
grid_points,
indices,
filename,
)
if vals:
colmat_at_sigma, gamma_at_sigma, temperatures = vals
else:
if log_level:
print(
"Collision at (grid point %d, band index %d) "
"doesn't exist." % (grid_points[0], 1)
)
return False
if not arrays_allocated:
arrays_allocated = True
# The following invokes self._allocate_values()
lbte.temperatures = temperatures
for i, gp in enumerate(grid_points):
if not _collect_collision_gp(
lbte.collision_matrix[i_sigma],
lbte.gamma[i_sigma],
temperatures,
mesh,
sigma,
sigma_cutoff,
i,
gp,
bz_grid.bzg2grg,
indices,
is_reducible_collision_matrix,
filename,
log_level,
):
num_band = lbte.collision_matrix.shape[3]
for i_band in range(num_band):
if not _collect_collision_band(
lbte.collision_matrix[i_sigma],
lbte.gamma[i_sigma],
temperatures,
mesh,
sigma,
sigma_cutoff,
i,
gp,
bz_grid.bzg2grg,
i_band,
indices,
is_reducible_collision_matrix,
filename,
log_level,
):
return False
read_from = "grid_points"
return read_from
def _allocate_collision(
for_gps,
mesh,
sigma,
sigma_cutoff,
grid_points,
indices,
filename,
):
if for_gps:
collision = read_collision_from_hdf5(
mesh,
indices=indices,
grid_point=grid_points[0],
sigma=sigma,
sigma_cutoff=sigma_cutoff,
filename=filename,
only_temperatures=True,
verbose=False,
)
else:
collision = read_collision_from_hdf5(
mesh,
indices=indices,
grid_point=grid_points[0],
band_index=0,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
filename=filename,
only_temperatures=True,
verbose=False,
)
if collision is None:
return False
temperatures = collision[2]
return None, None, temperatures
def _collect_collision_gp(
colmat_at_sigma,
gamma_at_sigma,
temperatures,
mesh,
sigma,
sigma_cutoff,
i,
gp,
bzg2grg,
indices,
is_reducible_collision_matrix,
filename,
log_level,
):
collision_gp = read_collision_from_hdf5(
mesh,
indices=indices,
grid_point=gp,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
filename=filename,
verbose=(log_level > 0),
)
if log_level:
sys.stdout.flush()
if not collision_gp:
return False
(colmat_at_gp, gamma_at_gp, temperatures_at_gp) = collision_gp
if is_reducible_collision_matrix:
igp = bzg2grg[gp]
else:
igp = i
gamma_at_sigma[:, igp] = gamma_at_gp
colmat_at_sigma[:, igp] = colmat_at_gp[0]
temperatures[:] = temperatures_at_gp
return True
def _collect_collision_band(
colmat_at_sigma,
gamma_at_sigma,
temperatures,
mesh,
sigma,
sigma_cutoff,
i,
gp,
bzg2grg,
j,
indices,
is_reducible_collision_matrix,
filename,
log_level,
):
collision_band = read_collision_from_hdf5(
mesh,
indices=indices,
grid_point=gp,
band_index=j,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
filename=filename,
verbose=(log_level > 0),
)
if log_level:
sys.stdout.flush()
if collision_band is False:
return False
(colmat_at_band, gamma_at_band, temperatures_at_band) = collision_band
if is_reducible_collision_matrix:
igp = bzg2grg[gp]
else:
igp = i
gamma_at_sigma[:, igp, j] = gamma_at_band[0]
colmat_at_sigma[:, igp, j] = colmat_at_band[0]
temperatures[:] = temperatures_at_band
return True

View File

@ -0,0 +1,735 @@
"""Init lattice thermal conductivity classes with RTA."""
# Copyright (C) 2020 Atsushi Togo
# All rights reserved.
#
# This file is part of phono3py.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# * Neither the name of the phonopy project nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from typing import Optional, Union, cast
import numpy as np
from phono3py.conductivity.base import get_unit_to_WmK
from phono3py.conductivity.kubo_rta import ConductivityKuboRTA
from phono3py.conductivity.rta import ConductivityRTA
from phono3py.conductivity.rta_base import ConductivityRTABase
from phono3py.conductivity.utils import write_pp_interaction
from phono3py.conductivity.wigner_rta import ConductivityWignerRTA
from phono3py.file_IO import (
read_gamma_from_hdf5,
write_gamma_detail_to_hdf5,
write_kappa_to_hdf5,
)
from phono3py.phonon3.interaction import Interaction, all_bands_exist
from phono3py.phonon3.triplets import get_all_triplets
cond_RTA_type = Union[ConductivityRTA, ConductivityWignerRTA, ConductivityKuboRTA]
def get_thermal_conductivity_RTA(
interaction: Interaction,
temperatures=None,
sigmas=None,
sigma_cutoff=None,
mass_variances=None,
grid_points=None,
is_isotope=False,
boundary_mfp=None, # in micrometer
use_ave_pp=False,
is_kappa_star=True,
gv_delta_q=None,
is_full_pp=False,
is_N_U=False,
conductivity_type=None,
write_gamma=False,
read_gamma=False,
write_kappa=False,
write_pp=False,
read_pp=False,
write_gamma_detail=False,
compression="gzip",
input_filename=None,
output_filename=None,
log_level=0,
):
"""Run RTA thermal conductivity calculation."""
if temperatures is None:
_temperatures = np.arange(0, 1001, 10, dtype="double")
else:
_temperatures = temperatures
if conductivity_type == "wigner":
conductivity_RTA_class = ConductivityWignerRTA
elif conductivity_type == "kubo":
conductivity_RTA_class = ConductivityKuboRTA
else:
conductivity_RTA_class = ConductivityRTA
if log_level:
print(
"-------------------- Lattice thermal conductivity (RTA) "
"--------------------"
)
br = conductivity_RTA_class(
interaction,
grid_points=grid_points,
temperatures=_temperatures,
sigmas=sigmas,
sigma_cutoff=sigma_cutoff,
is_isotope=is_isotope,
mass_variances=mass_variances,
boundary_mfp=boundary_mfp,
use_ave_pp=use_ave_pp,
is_kappa_star=is_kappa_star,
gv_delta_q=gv_delta_q,
is_full_pp=is_full_pp,
read_pp=read_pp,
store_pp=write_pp,
pp_filename=input_filename,
is_N_U=is_N_U,
is_gamma_detail=write_gamma_detail,
log_level=log_level,
)
if read_gamma:
if not _set_gamma_from_file(br, filename=input_filename):
print("Reading collisions failed.")
return False
for i in br:
if write_pp:
write_pp_interaction(
br, interaction, i, compression=compression, filename=output_filename
)
if write_gamma:
ConductivityRTAWriter.write_gamma(
br,
interaction,
i,
compression=compression,
filename=output_filename,
verbose=log_level,
)
if write_gamma_detail:
ConductivityRTAWriter.write_gamma_detail(
br,
interaction,
i,
compression=compression,
filename=output_filename,
verbose=log_level,
)
if grid_points is None and all_bands_exist(interaction):
br.set_kappa_at_sigmas()
if log_level:
if conductivity_type == "wigner":
ShowCalcProgress.kappa_Wigner_RTA(
cast(ConductivityWignerRTA, br), log_level
)
else:
ShowCalcProgress.kappa_RTA(cast(ConductivityRTA, br), log_level)
if write_kappa:
ConductivityRTAWriter.write_kappa(
br,
interaction.primitive.volume,
compression=compression,
filename=output_filename,
log_level=log_level,
)
return br
class ShowCalcProgress:
"""Show calculation progress."""
@staticmethod
def kappa_RTA(br: ConductivityRTA, log_level):
"""Show RTA calculation progress."""
temperatures = br.temperatures
sigmas = br.sigmas
kappa = br.kappa
num_ignored_phonon_modes = br.number_of_ignored_phonon_modes
num_band = br.frequencies.shape[1]
num_phonon_modes = br.number_of_sampling_grid_points * num_band
for i, sigma in enumerate(sigmas):
text = "----------- Thermal conductivity (W/m-k) "
if sigma:
text += "for sigma=%s -----------" % sigma
else:
text += "with tetrahedron method -----------"
print(text)
if log_level > 1:
print(
("#%6s " + " %-10s" * 6 + "#ipm")
% ("T(K)", "xx", "yy", "zz", "yz", "xz", "xy")
)
for j, (t, k) in enumerate(zip(temperatures, kappa[i])):
print(
("%7.1f" + " %10.3f" * 6 + " %d/%d")
% (
(t,)
+ tuple(k)
+ (num_ignored_phonon_modes[i, j], num_phonon_modes)
)
)
else:
print(
("#%6s " + " %-10s" * 6)
% ("T(K)", "xx", "yy", "zz", "yz", "xz", "xy")
)
for t, k in zip(temperatures, kappa[i]):
print(("%7.1f " + " %10.3f" * 6) % ((t,) + tuple(k)))
print("", flush=True)
@staticmethod
def kappa_Wigner_RTA(br: ConductivityWignerRTA, log_level):
"""Show Wigner-RTA calculation progress."""
temperatures = br.temperatures
sigmas = br.sigmas
kappa_TOT_RTA = br.kappa_TOT_RTA
kappa_P_RTA = br.kappa_P_RTA
kappa_C = br.kappa_C
num_ignored_phonon_modes = br.number_of_ignored_phonon_modes
num_band = br.frequencies.shape[1]
num_phonon_modes = br.number_of_sampling_grid_points * num_band
for i, sigma in enumerate(sigmas):
text = "----------- Thermal conductivity (W/m-k) "
if sigma:
text += "for sigma=%s -----------" % sigma
else:
text += "with tetrahedron method -----------"
print(text)
if log_level > 1:
print(
("#%6s " + " %-10s" * 6 + "#ipm")
% (" \t T(K)", "xx", "yy", "zz", "yz", "xz", "xy")
)
for j, (t, k) in enumerate(zip(temperatures, kappa_P_RTA[i])):
print(
"K_P\t"
+ ("%7.1f" + " %10.3f" * 6 + " %d/%d")
% (
(t,)
+ tuple(k)
+ (num_ignored_phonon_modes[i, j], num_phonon_modes)
)
)
print(" ")
for j, (t, k) in enumerate(zip(temperatures, kappa_C[i])):
print(
"K_C\t"
+ ("%7.1f" + " %10.3f" * 6 + " %d/%d")
% (
(t,)
+ tuple(k)
+ (num_ignored_phonon_modes[i, j], num_phonon_modes)
)
)
print(" ")
for j, (t, k) in enumerate(zip(temperatures, kappa_TOT_RTA[i])):
print(
"K_T\t"
+ ("%7.1f" + " %10.3f" * 6 + " %d/%d")
% (
(t,)
+ tuple(k)
+ (num_ignored_phonon_modes[i, j], num_phonon_modes)
)
)
else:
print(
("#%6s " + " %-10s" * 6)
% (" \t T(K)", "xx", "yy", "zz", "yz", "xz", "xy")
)
if kappa_P_RTA is not None:
for t, k in zip(temperatures, kappa_P_RTA[i]):
print("K_P\t" + ("%7.1f " + " %10.3f" * 6) % ((t,) + tuple(k)))
print(" ")
for t, k in zip(temperatures, kappa_C[i]):
print("K_C\t" + ("%7.1f " + " %10.3f" * 6) % ((t,) + tuple(k)))
print(" ")
for t, k in zip(temperatures, kappa_TOT_RTA[i]):
print("K_T\t" + ("%7.1f " + " %10.3f" * 6) % ((t,) + tuple(k)))
print("", flush=True)
class ConductivityRTAWriter:
"""Collection of result writers."""
@staticmethod
def write_gamma(
br: cond_RTA_type,
interaction: Interaction,
i: int,
compression: str = "gzip",
filename: Optional[str] = None,
verbose: bool = True,
):
"""Write mode kappa related properties into a hdf5 file."""
grid_points = br.grid_points
if isinstance(br, ConductivityRTA):
group_velocities_i = br.group_velocities[i]
gv_by_gv_i = br.gv_by_gv[i]
else:
group_velocities_i = None
gv_by_gv_i = None
if isinstance(br, ConductivityWignerRTA):
velocity_operator_i = br.velocity_operator[i]
else:
velocity_operator_i = None
if isinstance(br, (ConductivityRTA, ConductivityWignerRTA)):
mode_heat_capacities = br.mode_heat_capacities
else:
mode_heat_capacities = None
ave_pp = br.averaged_pp_interaction
mesh = br.mesh_numbers
bz_grid = br.bz_grid
temperatures = br.temperatures
gamma = br.gamma
gamma_isotope = br.gamma_isotope
sigmas = br.sigmas
sigma_cutoff = br.sigma_cutoff_width
volume = interaction.primitive.volume
gamma_N, gamma_U = br.get_gamma_N_U()
gp = grid_points[i]
if all_bands_exist(interaction):
if ave_pp is None:
ave_pp_i = None
else:
ave_pp_i = ave_pp[i]
frequencies = interaction.get_phonons()[0][gp]
for j, sigma in enumerate(sigmas):
if gamma_isotope is None:
gamma_isotope_at_sigma = None
else:
gamma_isotope_at_sigma = gamma_isotope[j, i]
if gamma_N is None:
gamma_N_at_sigma = None
else:
gamma_N_at_sigma = gamma_N[j, :, i]
if gamma_U is None:
gamma_U_at_sigma = None
else:
gamma_U_at_sigma = gamma_U[j, :, i]
write_kappa_to_hdf5(
temperatures,
mesh,
bz_grid=bz_grid,
frequency=frequencies,
group_velocity=group_velocities_i,
gv_by_gv=gv_by_gv_i,
velocity_operator=velocity_operator_i,
heat_capacity=mode_heat_capacities[:, i],
gamma=gamma[j, :, i],
gamma_isotope=gamma_isotope_at_sigma,
gamma_N=gamma_N_at_sigma,
gamma_U=gamma_U_at_sigma,
averaged_pp_interaction=ave_pp_i,
grid_point=gp,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
kappa_unit_conversion=get_unit_to_WmK() / volume,
compression=compression,
filename=filename,
verbose=verbose,
)
else:
for j, sigma in enumerate(sigmas):
for k, bi in enumerate(interaction.band_indices):
if group_velocities_i is None:
group_velocities_ik = None
else:
group_velocities_ik = group_velocities_i[k]
if velocity_operator_i is None:
velocity_operator_ik = None
else:
velocity_operator_ik = velocity_operator_i[k]
if gv_by_gv_i is None:
gv_by_gv_ik = None
else:
gv_by_gv_ik = gv_by_gv_i[k]
if ave_pp is None:
ave_pp_ik = None
else:
ave_pp_ik = ave_pp[i, k]
frequencies = interaction.get_phonons()[0][gp, bi]
if gamma_isotope is not None:
gamma_isotope_at_sigma = gamma_isotope[j, i, k]
else:
gamma_isotope_at_sigma = None
if gamma_N is None:
gamma_N_at_sigma = None
else:
gamma_N_at_sigma = gamma_N[j, :, i, k]
if gamma_U is None:
gamma_U_at_sigma = None
else:
gamma_U_at_sigma = gamma_U[j, :, i, k]
write_kappa_to_hdf5(
temperatures,
mesh,
bz_grid=bz_grid,
frequency=frequencies,
group_velocity=group_velocities_ik,
gv_by_gv=gv_by_gv_ik,
velocity_operator=velocity_operator_ik,
heat_capacity=mode_heat_capacities[:, i, k],
gamma=gamma[j, :, i, k],
gamma_isotope=gamma_isotope_at_sigma,
gamma_N=gamma_N_at_sigma,
gamma_U=gamma_U_at_sigma,
averaged_pp_interaction=ave_pp_ik,
grid_point=gp,
band_index=bi,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
kappa_unit_conversion=get_unit_to_WmK() / volume,
compression=compression,
filename=filename,
verbose=verbose,
)
@staticmethod
def write_kappa(
br: cond_RTA_type,
volume: float,
compression: str = "gzip",
filename: Optional[str] = None,
log_level: int = 0,
):
"""Write kappa related properties into a hdf5 file."""
temperatures = br.temperatures
sigmas = br.sigmas
sigma_cutoff = br.sigma_cutoff_width
gamma = br.gamma
gamma_isotope = br.gamma_isotope
gamma_N, gamma_U = br.get_gamma_N_U()
mesh = br.mesh_numbers
bz_grid = br.bz_grid
frequencies = br.frequencies
if isinstance(br, ConductivityRTA):
kappa = br.kappa
mode_kappa = br.mode_kappa
gv = br.group_velocities
gv_by_gv = br.gv_by_gv
else:
kappa = None
mode_kappa = None
gv = None
gv_by_gv = None
if isinstance(br, ConductivityWignerRTA):
kappa_TOT_RTA = br.kappa_TOT_RTA
kappa_P_RTA = br.kappa_P_RTA
kappa_C = br.kappa_C
mode_kappa_P_RTA = br.mode_kappa_P_RTA
mode_kappa_C = br.mode_kappa_C
else:
kappa_TOT_RTA = None
kappa_P_RTA = None
kappa_C = None
mode_kappa_P_RTA = None
mode_kappa_C = None
if isinstance(br, (ConductivityRTA, ConductivityWignerRTA)):
mode_cv = br.mode_heat_capacities
else:
mode_cv = None
ave_pp = br.averaged_pp_interaction
qpoints = br.qpoints
grid_points = br.grid_points
weights = br.grid_weights
boundary_mfp = br.boundary_mfp
for i, sigma in enumerate(sigmas):
if kappa is None:
kappa_at_sigma = None
else:
kappa_at_sigma = kappa[i]
if mode_kappa is None:
mode_kappa_at_sigma = None
else:
mode_kappa_at_sigma = mode_kappa[i]
if kappa_TOT_RTA is None:
kappa_TOT_RTA_at_sigma = None
else:
kappa_TOT_RTA_at_sigma = kappa_TOT_RTA[i]
if kappa_P_RTA is None:
kappa_P_RTA_at_sigma = None
else:
kappa_P_RTA_at_sigma = kappa_P_RTA[i]
if kappa_C is None:
kappa_C_at_sigma = None
else:
kappa_C_at_sigma = kappa_C[i]
if mode_kappa_P_RTA is None:
mode_kappa_P_RTA_at_sigma = None
else:
mode_kappa_P_RTA_at_sigma = mode_kappa_P_RTA[i]
if mode_kappa_C is None:
mode_kappa_C_at_sigma = None
else:
mode_kappa_C_at_sigma = mode_kappa_C[i]
if gamma_isotope is not None:
gamma_isotope_at_sigma = gamma_isotope[i]
else:
gamma_isotope_at_sigma = None
if gamma_N is None:
gamma_N_at_sigma = None
else:
gamma_N_at_sigma = gamma_N[i]
if gamma_U is None:
gamma_U_at_sigma = None
else:
gamma_U_at_sigma = gamma_U[i]
write_kappa_to_hdf5(
temperatures,
mesh,
boundary_mfp=boundary_mfp,
bz_grid=bz_grid,
frequency=frequencies,
group_velocity=gv,
gv_by_gv=gv_by_gv,
heat_capacity=mode_cv,
kappa=kappa_at_sigma,
mode_kappa=mode_kappa_at_sigma,
kappa_TOT_RTA=kappa_TOT_RTA_at_sigma,
kappa_P_RTA=kappa_P_RTA_at_sigma,
kappa_C=kappa_C_at_sigma,
mode_kappa_P_RTA=mode_kappa_P_RTA_at_sigma,
mode_kappa_C=mode_kappa_C_at_sigma,
gamma=gamma[i],
gamma_isotope=gamma_isotope_at_sigma,
gamma_N=gamma_N_at_sigma,
gamma_U=gamma_U_at_sigma,
averaged_pp_interaction=ave_pp,
qpoint=qpoints,
grid_point=grid_points,
weight=weights,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
kappa_unit_conversion=get_unit_to_WmK() / volume,
compression=compression,
filename=filename,
verbose=log_level,
)
@staticmethod
def write_gamma_detail(
br: cond_RTA_type,
interaction: Interaction,
i: int,
compression: str = "gzip",
filename: Optional[str] = None,
verbose: bool = True,
):
"""Write detailed Gamma values to hdf5 files."""
gamma_detail = br.get_gamma_detail_at_q()
temperatures = br.temperatures
mesh = br.mesh_numbers
bz_grid = br.bz_grid
grid_points = br.grid_points
gp = grid_points[i]
sigmas = br.sigmas
sigma_cutoff = br.sigma_cutoff_width
triplets, weights, _, _ = interaction.get_triplets_at_q()
all_triplets = get_all_triplets(gp, interaction.bz_grid)
if all_bands_exist(interaction):
for sigma in sigmas:
write_gamma_detail_to_hdf5(
temperatures,
mesh,
bz_grid=bz_grid,
gamma_detail=gamma_detail,
grid_point=gp,
triplet=triplets,
weight=weights,
triplet_all=all_triplets,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
compression=compression,
filename=filename,
verbose=verbose,
)
else:
for sigma in sigmas:
for k, bi in enumerate(interaction.get_band_indices()):
write_gamma_detail_to_hdf5(
temperatures,
mesh,
bz_grid=bz_grid,
gamma_detail=gamma_detail[:, :, k, :, :],
grid_point=gp,
triplet=triplets,
weight=weights,
band_index=bi,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
compression=compression,
filename=filename,
verbose=verbose,
)
def _set_gamma_from_file(
br: ConductivityRTABase, filename: Optional[str] = None, verbose: bool = True
):
"""Read kappa-*.hdf5 files for thermal conductivity calculation.
If kappa-m*.hdf5 that contains all data is not found, kappa-m*-gp*.hdf5
files at grid points are searched. If any of those files are not found,
kappa-m*-gp*-b*.hdf5 files at grid points and bands are searched. If any
of those files are not found, it fails.
br : ConductivityRTABase
RTA lattice thermal conductivity instance.
filename : str, optional
This string is inserted in the filename as kappa-m*.{filename}.hdf5.
verbose : bool, optional
Show text output or not.
"""
sigmas = br.sigmas
sigma_cutoff = br.sigma_cutoff_width
mesh = br.mesh_numbers
grid_points = br.grid_points
temperatures = br.temperatures
num_band = br.frequencies.shape[1]
gamma = np.zeros(
(len(sigmas), len(temperatures), len(grid_points), num_band), dtype="double"
)
gamma_N = np.zeros_like(gamma)
gamma_U = np.zeros_like(gamma)
gamma_iso = np.zeros((len(sigmas), len(grid_points), num_band), dtype="double")
ave_pp = np.zeros((len(grid_points), num_band), dtype="double")
is_gamma_N_U_in = False
is_ave_pp_in = False
read_succeeded = True
for j, sigma in enumerate(sigmas):
data, full_filename = read_gamma_from_hdf5(
mesh,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
filename=filename,
)
if data:
if verbose:
print("Read data from %s." % full_filename)
gamma[j] = data["gamma"]
if "gamma_isotope" in data:
gamma_iso[j] = data["gamma_isotope"]
if "gamma_N" in data:
is_gamma_N_U_in = True
gamma_N[j] = data["gamma_N"]
gamma_U[j] = data["gamma_U"]
if "ave_pp" in data:
is_ave_pp_in = True
ave_pp[:] = data["ave_pp"]
else:
if verbose:
print(
"%s not found. Look for hdf5 files at grid points." % full_filename
)
for i, gp in enumerate(grid_points):
data_gp, full_filename = read_gamma_from_hdf5(
mesh,
grid_point=gp,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
filename=filename,
)
if data_gp:
if verbose:
print("Read data from %s." % full_filename)
gamma[j, :, i] = data_gp["gamma"]
if "gamma_iso" in data_gp:
gamma_iso[j, i] = data_gp["gamma_iso"]
if "gamma_N" in data_gp:
is_gamma_N_U_in = True
gamma_N[j, :, i] = data_gp["gamma_N"]
gamma_U[j, :, i] = data_gp["gamma_U"]
if "ave_pp" in data_gp:
is_ave_pp_in = True
ave_pp[i] = data_gp["ave_pp"]
else:
if verbose:
print(
"%s not found. Look for hdf5 files at bands."
% full_filename
)
for bi in range(num_band):
data_band, full_filename = read_gamma_from_hdf5(
mesh,
grid_point=gp,
band_index=bi,
sigma=sigma,
sigma_cutoff=sigma_cutoff,
filename=filename,
)
if data_band:
if verbose:
print("Read data from %s." % full_filename)
gamma[j, :, i, bi] = data_band["gamma"]
if "gamma_iso" in data_band:
gamma_iso[j, i, bi] = data_band["gamma_iso"]
if "gamma_N" in data_band:
is_gamma_N_U_in = True
gamma_N[j, :, i, bi] = data_band["gamma_N"]
gamma_U[j, :, i, bi] = data_band["gamma_U"]
if "ave_pp" in data_band:
is_ave_pp_in = True
ave_pp[i, bi] = data_band["ave_pp"]
else:
if verbose:
print("%s not found." % full_filename)
read_succeeded = False
if read_succeeded:
br.gamma = gamma
if is_ave_pp_in:
br.set_averaged_pp_interaction(ave_pp)
if is_gamma_N_U_in:
br.set_gamma_N_U(gamma_N, gamma_U)
return True
else:
return False

View File

@ -35,8 +35,10 @@
# POSSIBILITY OF SUCH DAMAGE.
import numpy as np
from phonopy.units import Kb, THzToEv
from phonopy.physical_units import get_physical_units
from phono3py.conductivity.base import get_kstar_order, get_multiplicity_at_q
from phono3py.phonon.grid import get_qpoints_from_bz_grid_points
from phono3py.phonon.group_velocity_matrix import GroupVelocityMatrix
from phono3py.phonon.heat_capacity_matrix import mode_cv_matrix
@ -71,11 +73,11 @@ class ConductivityKuboMixIn:
"""
irgp = self._grid_points[i_gp]
freqs = self._frequencies[irgp] * THzToEv
cutoff = self._pp.cutoff_frequency * THzToEv
freqs = self._frequencies[irgp] * get_physical_units().THzToEv
cutoff = self._pp.cutoff_frequency * get_physical_units().THzToEv
for i_temp, temp in enumerate(self._temperatures):
if (freqs / (temp * Kb) > 100).any():
if (freqs / (temp * get_physical_units().KB) > 100).any():
continue
cvm = mode_cv_matrix(temp, freqs, cutoff=cutoff)
self._cv_mat[i_temp, i_data] = cvm[self._pp.band_indices, :]
@ -102,7 +104,9 @@ class ConductivityKuboMixIn:
"""
irgp = self._grid_points[i_gp]
self._velocity_obj.run([self._get_qpoint_from_gp_index(irgp)])
self._velocity_obj.run(
[get_qpoints_from_bz_grid_points(irgp, self._pp.bz_grid)]
)
gvm = np.zeros(self._gv_mat.shape[1:], dtype=self._complex_dtype, order="C")
gv = np.zeros(self._gv.shape[1:], dtype="double", order="C")
for i in range(3):
@ -136,8 +140,15 @@ class ConductivityKuboMixIn:
Number of kstar arms.
"""
multi = self._get_multiplicity_at_q(i_gp)
q = self._get_qpoint_from_gp_index(self._grid_points[i_gp])
if self._is_kappa_star:
multi = get_multiplicity_at_q(
self._grid_points[i_gp],
self._pp,
self._point_operations,
)
else:
multi = 1
q = get_qpoints_from_bz_grid_points(self._grid_points[i_gp], self._pp.bz_grid)
qpoints = [np.dot(r, q) for r in self._point_operations]
self._velocity_obj.run(qpoints)
@ -151,5 +162,10 @@ class ConductivityKuboMixIn:
gvm_by_gvm = np.multiply(gvm[a], gvm[b].T)
gvm_sum2[:, :, i_pair] += gvm_by_gvm[self._pp.band_indices, :]
gvm_sum2 /= multi
return gvm_sum2, self._get_kstar_order(i_gp, multi)
kstar_order = get_kstar_order(
self._grid_weights[i_gp],
multi,
self._point_operations,
verbose=self._log_level > 0,
)
return gvm_sum2, kstar_order

View File

@ -0,0 +1,188 @@
"""Kubo thermal conductivity RTA class."""
# Copyright (C) 2022 Atsushi Togo
# All rights reserved.
#
# This file is part of phono3py.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# * Neither the name of the phonopy project nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import numpy as np
from phono3py.conductivity.kubo_base import ConductivityKuboMixIn
from phono3py.conductivity.rta_base import ConductivityRTABase
from phono3py.phonon3.interaction import Interaction
class ConductivityKuboRTA(ConductivityKuboMixIn, ConductivityRTABase):
"""Class of Kubo lattice thermal conductivity under RTA."""
def __init__(
self,
interaction: Interaction,
grid_points=None,
temperatures=None,
sigmas=None,
sigma_cutoff=None,
is_isotope=False,
mass_variances=None,
boundary_mfp=None, # in micrometer
use_ave_pp=False,
is_kappa_star=True,
gv_delta_q=None,
is_full_pp=False,
read_pp=False,
store_pp=False,
pp_filename=None,
is_N_U=False,
is_gamma_detail=False,
is_frequency_shift_by_bubble=False,
log_level=0,
):
"""Init method."""
self._cv_mat = None
self._gv_mat = None
self._kappa = None
super().__init__(
interaction,
grid_points=grid_points,
temperatures=temperatures,
sigmas=sigmas,
sigma_cutoff=sigma_cutoff,
is_isotope=is_isotope,
mass_variances=mass_variances,
boundary_mfp=boundary_mfp,
use_ave_pp=use_ave_pp,
is_kappa_star=is_kappa_star,
gv_delta_q=gv_delta_q,
is_full_pp=is_full_pp,
read_pp=read_pp,
store_pp=store_pp,
pp_filename=pp_filename,
is_N_U=is_N_U,
is_gamma_detail=is_gamma_detail,
is_frequency_shift_by_bubble=is_frequency_shift_by_bubble,
log_level=log_level,
)
def set_kappa_at_sigmas(self):
"""Calculate kappa from ph-ph interaction results."""
for i_gp, _ in enumerate(self._grid_points):
frequencies = self._frequencies[self._grid_points[i_gp]]
for j in range(len(self._sigmas)):
for k in range(len(self._temperatures)):
g_sum = self._get_main_diagonal(i_gp, j, k)
for i_band, freq in enumerate(frequencies):
if freq < self._pp.cutoff_frequency:
self._num_ignored_phonon_modes[j, k] += 1
continue
self._set_kappa_at_sigmas(
j, k, i_gp, i_band, g_sum, frequencies
)
N = self._num_sampling_grid_points
self._kappa = self._mode_kappa_mat.sum(axis=2).sum(axis=2).sum(axis=2).real / N
def _set_kappa_at_sigmas(self, j, k, i_gp, i_band, g_sum, frequencies):
gvm_sum2 = self._gv_mat_sum2[i_gp]
cvm = self._cv_mat[k, i_gp]
for j_band, freq in enumerate(frequencies):
if freq < self._pp.cutoff_frequency:
return
g = g_sum[i_band] + g_sum[j_band]
for i_pair, _ in enumerate(
([0, 0], [1, 1], [2, 2], [1, 2], [0, 2], [0, 1])
):
old_settings = np.seterr(all="raise")
try:
self._mode_kappa_mat[j, k, i_gp, i_band, j_band, i_pair] = (
cvm[i_band, j_band]
* gvm_sum2[i_band, j_band, i_pair]
* g
/ ((frequencies[j_band] - frequencies[i_band]) ** 2 + g**2)
* self._conversion_factor
)
except FloatingPointError:
# supposed that g is almost 0 and |gv|=0
pass
except Exception:
gp = self._grid_points[i_gp]
print("=" * 26 + " Warning " + "=" * 26)
print(
" Unexpected physical condition of ph-ph "
"interaction calculation was found."
)
print(
" g=%f at gp=%d, band=%d, freq=%f, band=%d, freq=%f"
% (
g_sum[i_band],
gp,
i_band + 1,
frequencies[i_band],
j_band + 1,
frequencies[j_band],
)
)
print("=" * 61)
np.seterr(**old_settings)
def _allocate_values(self):
super()._allocate_values()
num_band0 = len(self._pp.band_indices)
num_band = len(self._pp.primitive) * 3
num_grid_points = len(self._grid_points)
num_temp = len(self._temperatures)
self._cv_mat = np.zeros(
(num_temp, num_grid_points, num_band0, num_band), dtype="double", order="C"
)
self._gv_mat = np.zeros(
(num_grid_points, num_band0, num_band, 3),
dtype=self._complex_dtype,
order="C",
)
self._gv_mat_sum2 = np.zeros(
(num_grid_points, num_band0, num_band, 6),
dtype=self._complex_dtype,
order="C",
)
# kappa and mode_kappa_mat are accessed when all bands exist, i.e.,
# num_band0==num_band.
self._kappa = np.zeros(
(len(self._sigmas), num_temp, 6), dtype="double", order="C"
)
self._mode_kappa_mat = np.zeros(
(len(self._sigmas), num_temp, num_grid_points, num_band, num_band, 6),
dtype=self._complex_dtype,
order="C",
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,528 @@
"""Lattice thermal conductivity calculation base class with RTA."""
# Copyright (C) 2020 Atsushi Togo
# All rights reserved.
#
# This file is part of phono3py.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# * Neither the name of the phonopy project nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import annotations
import warnings
from abc import abstractmethod
import numpy as np
from phonopy.physical_units import get_physical_units
from phono3py.conductivity.base import ConductivityBase
from phono3py.file_IO import read_pp_from_hdf5
from phono3py.other.tetrahedron_method import get_tetrahedra_relative_grid_address
from phono3py.phonon.grid import (
get_grid_points_by_rotations,
get_qpoints_from_bz_grid_points,
)
from phono3py.phonon3.imag_self_energy import ImagSelfEnergy, average_by_degeneracy
from phono3py.phonon3.interaction import Interaction
class ConductivityRTABase(ConductivityBase):
"""Base class of ConductivityRTA*.
This is a base class of RTA classes.
"""
def __init__(
self,
interaction: Interaction,
grid_points: np.ndarray | None = None,
temperatures: list | np.ndarray | None = None,
sigmas: list | np.ndarray | None = None,
sigma_cutoff: float | None = None,
is_isotope: bool = False,
mass_variances: list | np.ndarray | None = None,
boundary_mfp: float | None = None, # in micrometer
use_ave_pp: bool = False,
is_kappa_star: bool = True,
is_full_pp: bool = False,
read_pp: bool = False,
store_pp: bool = False,
pp_filename: float | None = None,
is_N_U: bool = False,
is_gamma_detail: bool = False,
is_frequency_shift_by_bubble: bool = False,
log_level: int = 0,
):
"""Init method."""
self._is_N_U = is_N_U
self._is_gamma_detail = is_gamma_detail
self._is_frequency_shift_by_bubble = is_frequency_shift_by_bubble
self._gamma_N = None
self._gamma_U = None
self._gamma_detail_at_q = None
self._use_ave_pp = use_ave_pp
self._use_const_ave_pp = None
self._num_ignored_phonon_modes = None
super().__init__(
interaction,
grid_points=grid_points,
temperatures=temperatures,
sigmas=sigmas,
sigma_cutoff=sigma_cutoff,
is_isotope=is_isotope,
mass_variances=mass_variances,
boundary_mfp=boundary_mfp,
is_kappa_star=is_kappa_star,
is_full_pp=is_full_pp,
log_level=log_level,
)
self._use_const_ave_pp = self._pp.constant_averaged_interaction
self._read_pp = read_pp
self._store_pp = store_pp
self._pp_filename = pp_filename
if self._temperatures is not None:
self._allocate_values()
self._collision = ImagSelfEnergy(
self._pp, with_detail=(self._is_gamma_detail or self._is_N_U)
)
def get_gamma_N_U(self):
"""Return N and U parts of gamma."""
return (self._gamma_N, self._gamma_U)
def set_gamma_N_U(self, gamma_N, gamma_U):
"""Set N and U parts of gamma."""
self._gamma_N = gamma_N
self._gamma_U = gamma_U
def get_gamma_detail_at_q(self):
"""Return contribution of each triplet to gamma at current q-point."""
return self._gamma_detail_at_q
def get_number_of_ignored_phonon_modes(self):
"""Return number of ignored phonon modes."""
warnings.warn(
"Use attribute, number_of_ignored_phonon_modes",
DeprecationWarning,
stacklevel=2,
)
return self.number_of_ignored_phonon_modes
@property
def number_of_ignored_phonon_modes(self):
"""Return number of ignored phonon modes."""
return self._num_ignored_phonon_modes
def set_averaged_pp_interaction(self, ave_pp):
"""Set averaged ph-ph interaction."""
self._averaged_pp_interaction = ave_pp
@abstractmethod
def set_kappa_at_sigmas(self):
"""Must be implemented in the inherited class."""
raise NotImplementedError()
def _allocate_values(self):
if self._temperatures is None:
raise RuntimeError(
"Temperatures have not been set yet. "
"Set temperatures before this method."
)
num_band0 = len(self._pp.band_indices)
num_grid_points = len(self._grid_points)
num_temp = len(self._temperatures)
if not self._read_gamma:
self._gamma = np.zeros(
(len(self._sigmas), num_temp, num_grid_points, num_band0),
order="C",
dtype="double",
)
if self._is_gamma_detail or self._is_N_U:
self._gamma_N = np.zeros_like(self._gamma)
self._gamma_U = np.zeros_like(self._gamma)
if self._is_isotope:
self._gamma_iso = np.zeros(
(len(self._sigmas), num_grid_points, num_band0),
order="C",
dtype="double",
)
if self._is_full_pp or self._use_ave_pp or self._use_const_ave_pp:
self._averaged_pp_interaction = np.zeros(
(num_grid_points, num_band0), order="C", dtype="double"
)
self._num_ignored_phonon_modes = np.zeros(
(len(self._sigmas), num_temp), order="C", dtype="intc"
)
def _run_at_grid_point(self):
i_gp = self._grid_point_count
self._show_log_header(i_gp)
grid_point = self._grid_points[i_gp]
self._set_cv(i_gp, i_gp)
self._set_velocities(i_gp, i_gp)
if self._read_gamma:
if self._use_ave_pp:
self._collision.set_grid_point(grid_point)
self._set_gamma_at_sigmas(i_gp)
else:
self._collision.set_grid_point(grid_point)
num_triplets = len(self._pp.get_triplets_at_q()[0])
if self._log_level:
print("Number of triplets: %d" % num_triplets, flush=True)
if (
self._is_full_pp
or self._read_pp
or self._store_pp
or self._use_ave_pp
or self._use_const_ave_pp
or self._is_gamma_detail
):
self._set_gamma_at_sigmas(i_gp)
else: # can save memory space
self._set_gamma_at_sigmas_lowmem(i_gp)
if self._is_isotope and not self._read_gamma_iso:
gamma_iso = self._get_gamma_isotope_at_sigmas(i_gp)
self._gamma_iso[:, i_gp, :] = gamma_iso[:, self._pp.band_indices]
if self._log_level:
self._show_log(i_gp)
def _set_gamma_at_sigmas(self, i):
for j, sigma in enumerate(self._sigmas):
self._collision.set_sigma(sigma, sigma_cutoff=self._sigma_cutoff)
self._collision.run_integration_weights()
if self._log_level:
text = "Collisions will be calculated with "
if sigma is None:
text += "tetrahedron method."
else:
text += "sigma=%s" % sigma
if self._sigma_cutoff is None:
text += "."
else:
text += "(%4.2f SD)." % self._sigma_cutoff
print(text)
if self._read_pp:
pp, _g_zero = read_pp_from_hdf5(
self._pp.mesh_numbers,
grid_point=self._grid_points[i],
sigma=sigma,
sigma_cutoff=self._sigma_cutoff,
filename=self._pp_filename,
verbose=(self._log_level > 0),
)
_, g_zero = self._collision.get_integration_weights()
if self._log_level:
if len(self._sigmas) > 1:
print(
"Multiple sigmas or mixing smearing and "
"tetrahedron method is not supported."
)
if _g_zero is not None and (_g_zero != g_zero).any():
raise ValueError("Inconsistency found in g_zero.")
self._collision.set_interaction_strength(pp)
elif self._use_ave_pp:
self._collision.set_averaged_pp_interaction(
self._averaged_pp_interaction[i]
)
elif self._use_const_ave_pp:
if self._log_level:
print(
"Constant ph-ph interaction of %6.3e is used."
% self._pp.constant_averaged_interaction
)
self._collision.run_interaction()
self._averaged_pp_interaction[i] = self._pp.averaged_interaction
elif j != 0 and (self._is_full_pp or self._sigma_cutoff is None):
if self._log_level:
print("Existing ph-ph interaction is used.")
else:
if self._log_level:
print("Calculating ph-ph interaction...")
self._collision.run_interaction(is_full_pp=self._is_full_pp)
if self._is_full_pp:
self._averaged_pp_interaction[i] = self._pp.averaged_interaction
# Number of triplets depends on q-point.
# So this is allocated each time.
if self._is_gamma_detail:
num_temp = len(self._temperatures)
self._gamma_detail_at_q = np.empty(
((num_temp,) + self._pp.interaction_strength.shape),
dtype="double",
order="C",
)
self._gamma_detail_at_q[:] = 0
if self._log_level:
print("Calculating collisions at temperatures...")
for k, t in enumerate(self._temperatures):
self._collision.temperature = t
self._collision.run()
self._gamma[j, k, i] = self._collision.imag_self_energy
if self._is_N_U or self._is_gamma_detail:
g_N, g_U = self._collision.get_imag_self_energy_N_and_U()
self._gamma_N[j, k, i] = g_N
self._gamma_U[j, k, i] = g_U
if self._is_gamma_detail:
self._gamma_detail_at_q[k] = (
self._collision.get_detailed_imag_self_energy()
)
def _set_gamma_at_sigmas_lowmem(self, i):
"""Calculate gamma without storing ph-ph interaction strength.
`svecs` and `multi` below must not be simply replaced by
`self._pp.primitive.get_smallest_vectors()` because they must be in
dense format as always so in Interaction class instance.
`p2s`, `s2p`, and `masses` have to be also given from Interaction
class instance.
"""
num_band = len(self._pp.primitive) * 3
band_indices = self._pp.band_indices
(
svecs,
multi,
p2s,
s2p,
masses,
) = self._pp.get_primitive_and_supercell_correspondence()
triplets_at_q, weights_at_q, _, _ = self._pp.get_triplets_at_q()
if None in self._sigmas:
tetrahedra = get_tetrahedra_relative_grid_address(
self._pp.bz_grid.microzone_lattice
)
# It is assumed that self._sigmas = [None].
temperatures_THz = np.array(
self._temperatures * get_physical_units().KB / get_physical_units().THzToEv,
dtype="double",
)
for j, sigma in enumerate(self._sigmas):
self._collision.set_sigma(sigma)
if self._is_N_U:
collisions = np.zeros(
(2, len(self._temperatures), len(band_indices)),
dtype="double",
order="C",
)
else:
collisions = np.zeros(
(len(self._temperatures), len(band_indices)),
dtype="double",
order="C",
)
import phono3py._phono3py as phono3c
# True: OpenMP over triplets
# False: OpenMP over bands
if self._pp.openmp_per_triplets is None:
if len(triplets_at_q) > num_band:
openmp_per_triplets = True
else:
openmp_per_triplets = False
else:
openmp_per_triplets = self._pp.openmp_per_triplets
if sigma is None:
phono3c.pp_collision(
collisions,
np.array(
np.dot(tetrahedra, self._pp.bz_grid.P.T),
dtype="int64",
order="C",
),
self._frequencies,
self._eigenvectors,
triplets_at_q,
weights_at_q,
self._pp.bz_grid.addresses,
self._pp.bz_grid.gp_map,
self._pp.bz_grid.store_dense_gp_map * 1 + 1,
self._pp.bz_grid.D_diag,
self._pp.bz_grid.Q,
self._pp.fc3,
self._pp.fc3_nonzero_indices,
svecs,
multi,
masses,
p2s,
s2p,
band_indices,
temperatures_THz,
self._is_N_U * 1,
self._pp.symmetrize_fc3q * 1,
self._pp.make_r0_average * 1,
self._pp.all_shortest,
self._pp.cutoff_frequency,
openmp_per_triplets * 1,
)
else:
if self._sigma_cutoff is None:
sigma_cutoff = -1
else:
sigma_cutoff = float(self._sigma_cutoff)
phono3c.pp_collision_with_sigma(
collisions,
sigma,
sigma_cutoff,
self._frequencies,
self._eigenvectors,
triplets_at_q,
weights_at_q,
self._pp.bz_grid.addresses,
self._pp.bz_grid.D_diag,
self._pp.bz_grid.Q,
self._pp.fc3,
self._pp.fc3_nonzero_indices,
svecs,
multi,
masses,
p2s,
s2p,
band_indices,
temperatures_THz,
self._is_N_U * 1,
self._pp.symmetrize_fc3q * 1,
self._pp.make_r0_average * 1,
self._pp.all_shortest,
self._pp.cutoff_frequency,
openmp_per_triplets * 1,
)
col_unit_conv = self._collision.unit_conversion_factor
pp_unit_conv = self._pp.unit_conversion_factor
if self._is_N_U:
col = collisions.sum(axis=0)
col_N = collisions[0]
col_U = collisions[1]
else:
col = collisions
for k in range(len(self._temperatures)):
self._gamma[j, k, i, :] = average_by_degeneracy(
col[k] * col_unit_conv * pp_unit_conv,
band_indices,
self._frequencies[self._grid_points[i]],
)
if self._is_N_U:
self._gamma_N[j, k, i, :] = average_by_degeneracy(
col_N[k] * col_unit_conv * pp_unit_conv,
band_indices,
self._frequencies[self._grid_points[i]],
)
self._gamma_U[j, k, i, :] = average_by_degeneracy(
col_U[k] * col_unit_conv * pp_unit_conv,
band_indices,
self._frequencies[self._grid_points[i]],
)
def _show_log(self, i_gp):
q = get_qpoints_from_bz_grid_points(i_gp, self._pp.bz_grid)
gp = self._grid_points[i_gp]
frequencies = self._frequencies[gp][self._pp.band_indices]
gv = self._conductivity_components.group_velocities[i_gp]
if self._averaged_pp_interaction is not None:
ave_pp = self._averaged_pp_interaction[i_gp]
else:
ave_pp = None
self._show_log_value_names()
if self._log_level > 2:
self._show_log_values_on_kstar(frequencies, gv, ave_pp, gp, q)
else:
self._show_log_values(frequencies, gv, ave_pp)
print("", end="", flush=True)
def _show_log_values(self, frequencies, gv, ave_pp):
if self._is_full_pp or self._use_ave_pp or self._use_const_ave_pp:
for f, v, pp in zip(frequencies, gv, ave_pp):
print(
"%8.3f (%8.3f %8.3f %8.3f) %8.3f %11.3e"
% (f, v[0], v[1], v[2], np.linalg.norm(v), pp)
)
else:
for f, v in zip(frequencies, gv):
print(
"%8.3f (%8.3f %8.3f %8.3f) %8.3f"
% (f, v[0], v[1], v[2], np.linalg.norm(v))
)
def _show_log_values_on_kstar(self, frequencies, gv, ave_pp, gp, q):
rotation_map = get_grid_points_by_rotations(gp, self._pp.bz_grid)
for i, j in enumerate(np.unique(rotation_map)):
for k, (rot, rot_c) in enumerate(
zip(self._point_operations, self._rotations_cartesian)
):
if rotation_map[k] != j:
continue
print(
" k*%-2d (%5.2f %5.2f %5.2f)" % ((i + 1,) + tuple(np.dot(rot, q)))
)
if self._is_full_pp or self._use_ave_pp or self._use_const_ave_pp:
for f, v, pp in zip(frequencies, np.dot(rot_c, gv.T).T, ave_pp):
print(
"%8.3f (%8.3f %8.3f %8.3f) %8.3f %11.3e"
% (f, v[0], v[1], v[2], np.linalg.norm(v), pp)
)
else:
for f, v in zip(frequencies, np.dot(rot_c, gv.T).T):
print(
"%8.3f (%8.3f %8.3f %8.3f) %8.3f"
% (f, v[0], v[1], v[2], np.linalg.norm(v))
)
print("")
def _show_log_value_names(self):
if self._is_full_pp or self._use_ave_pp or self._use_const_ave_pp:
text = "Frequency group velocity (x, y, z) |gv| Pqj"
else:
text = "Frequency group velocity (x, y, z) |gv|"
if self._conductivity_components.gv_delta_q is None:
pass
else:
text += " (dq=%3.1e)" % self._conductivity_components.gv_delta_q
print(text)

File diff suppressed because it is too large Load Diff

View File

@ -35,47 +35,83 @@
# POSSIBILITY OF SUCH DAMAGE.
import textwrap
from typing import Optional
import numpy as np
from numpy.typing import NDArray
from phonopy.phonon.degeneracy import degenerate_sets
from phonopy.units import EV, Angstrom, Hbar, THz
from phonopy.physical_units import get_physical_units
from phono3py.conductivity.base import HeatCapacityMixIn
from phono3py.phonon.grid import get_grid_points_by_rotations
from phono3py.conductivity.base import ConductivityComponentsBase, get_heat_capacities
from phono3py.phonon.grid import (
get_grid_points_by_rotations,
get_qpoints_from_bz_grid_points,
)
from phono3py.phonon.velocity_operator import VelocityOperator
from phono3py.phonon3.interaction import Interaction
class ConductivityWignerMixIn(HeatCapacityMixIn):
"""Thermal conductivity mix-in for velocity operator.
def get_conversion_factor_WTE(volume):
"""Return conversion factor of thermal conductivity."""
return (
(get_physical_units().THz * get_physical_units().Angstrom)
** 2 # --> group velocity
* get_physical_units().EV # --> specific heat is in eV/
* get_physical_units().Hbar # --> transform lorentzian_div_hbar from eV^-1 to s
/ (volume * get_physical_units().Angstrom ** 3)
) # --> unit cell volume
This mix-in is included in `ConductivityWignerRTA` and `ConductivityWignerLBTE`.
class ConductivityWignerComponents(ConductivityComponentsBase):
"""Thermal conductivity components for velocity operator.
Used by `ConductivityWignerRTA` and `ConductivityWignerLBTE`.
"""
@property
def kappa_TOT_RTA(self):
"""Return kappa."""
return self._kappa_TOT_RTA
def __init__(
self,
pp: Interaction,
grid_points: NDArray[np.int64],
grid_weights: NDArray[np.int64],
point_operations: NDArray[np.int64],
rotations_cartesian: NDArray[np.int64],
temperatures: Optional[NDArray[np.float64]] = None,
is_kappa_star: bool = True,
gv_delta_q: Optional[float] = None,
is_reducible_collision_matrix: bool = False,
log_level: int = 0,
):
"""Init method."""
super().__init__(
pp,
grid_points=grid_points,
grid_weights=grid_weights,
point_operations=point_operations,
rotations_cartesian=rotations_cartesian,
temperatures=temperatures,
is_kappa_star=is_kappa_star,
is_reducible_collision_matrix=is_reducible_collision_matrix,
log_level=log_level,
)
@property
def kappa_P_RTA(self):
"""Return kappa."""
return self._kappa_P_RTA
self._gv_operator: np.ndarray
self._gv_operator_sum2: np.ndarray
@property
def kappa_C(self):
"""Return kappa."""
return self._kappa_C
if self._pp.dynamical_matrix is None:
raise RuntimeError("Interaction.init_dynamical_matrix() has to be called.")
self._velocity_obj = VelocityOperator(
self._pp.dynamical_matrix,
q_length=gv_delta_q,
symmetry=self._pp.primitive_symmetry,
frequency_factor_to_THz=self._pp.frequency_factor_to_THz,
)
@property
def mode_kappa_P_RTA(self):
"""Return mode_kappa."""
return self._mode_kappa_P_RTA
self._num_sampling_grid_points = 0
self._complex_dtype = "c%d" % (np.dtype("double").itemsize * 2)
@property
def mode_kappa_C(self):
"""Return mode_kappa."""
return self._mode_kappa_C
if self._temperatures is not None:
self._allocate_values()
@property
def velocity_operator(self):
@ -91,27 +127,34 @@ class ConductivityWignerMixIn(HeatCapacityMixIn):
"""Return gv_by_gv operator at grid points where mode kappa are calculated."""
return self._gv_operator_sum2
def _init_velocity(self, gv_delta_q):
self._velocity_obj = VelocityOperator(
self._pp.dynamical_matrix,
q_length=gv_delta_q,
symmetry=self._pp.primitive_symmetry,
frequency_factor_to_THz=self._pp.frequency_factor_to_THz,
)
def _set_velocities(self, i_gp, i_data):
def set_velocities(self, i_gp, i_data):
"""Set velocities at a grid point."""
self._set_gv_operator(i_gp, i_data)
self._set_gv_by_gv_operator(i_gp, i_data)
def set_heat_capacities(self, i_gp: int, i_data: int):
"""Set heat capacity at grid point and at data location."""
if self._temperatures is None:
raise RuntimeError(
"Temperatures have not been set yet. "
"Set temperatures before this method."
)
cv = get_heat_capacities(self._grid_points[i_gp], self._pp, self._temperatures)
self._cv[:, i_data, :] = cv
def _set_gv_operator(self, i_irgp, i_data):
"""Set velocity operator."""
irgp = self._grid_points[i_irgp]
self._velocity_obj.run([self._get_qpoint_from_gp_index(irgp)])
frequencies, _, _ = self._pp.get_phonons()
self._velocity_obj.run(
[get_qpoints_from_bz_grid_points(irgp, self._pp.bz_grid)]
)
gv_operator = self._velocity_obj.velocity_operators[0, :, :, :]
self._gv_operator[i_data] = gv_operator[self._pp.band_indices, :, :]
#
gv = np.einsum("iij->ij", gv_operator).real
deg_sets = degenerate_sets(self._frequencies[irgp])
deg_sets = degenerate_sets(frequencies[irgp])
# group velocities in the degenerate subspace are obtained diagonalizing the
# velocity operator in the subspace of degeneracy.
for id_dir in range(3):
@ -141,14 +184,14 @@ class ConductivityWignerMixIn(HeatCapacityMixIn):
# Sum all vxv at k*
for j, vxv in enumerate(([0, 0], [1, 1], [2, 2], [1, 2], [0, 2], [0, 1])):
# self._gv_sum2[i_data, :, j] = gv_by_gv_tensor[:, vxv[0], vxv[1]]
# self._gv_by_gv[i_data, :, j] = gv_by_gv_tensor[:, vxv[0], vxv[1]]
# here it is storing the 6 independent components of the v^i x v^j tensor
# i_data is the q-point index
# j indexes the 6 independent component of the symmetric tensor v^i x v^j
self._gv_operator_sum2[i_data, :, :, j] = gv_by_gv_operator_tensor[
:, :, vxv[0], vxv[1]
]
# self._gv_sum2[i_data, :, j] = gv_by_gv_tensor[:, vxv[0], vxv[1]]
# self._gv_by_gv[i_data, :, j] = gv_by_gv_tensor[:, vxv[0], vxv[1]]
def _get_gv_by_gv_operator(self, i_irgp, i_data):
if self._is_kappa_star:
@ -211,12 +254,23 @@ class ConductivityWignerMixIn(HeatCapacityMixIn):
return gv_by_gv_operator, order_kstar
def _allocate_values(self):
super()._allocate_values()
def get_conversion_factor_WTE(volume):
"""Return conversion factor of thermal conductivity."""
return (
(THz * Angstrom) ** 2 # ----> group velocity
* EV # ----> specific heat is in eV/
* Hbar # ----> transform lorentzian_div_hbar from eV^-1 to s
/ (volume * Angstrom**3)
) # ----> unit cell volume
num_band0 = len(self._pp.band_indices)
if self._is_reducible_collision_matrix:
num_grid_points = np.prod(self._pp.mesh_numbers)
else:
num_grid_points = len(self._grid_points)
num_band = len(self._pp.primitive) * 3
self._gv_operator = np.zeros(
(num_grid_points, num_band0, num_band, 3),
order="C",
dtype=self._complex_dtype,
)
self._gv_operator_sum2 = np.zeros(
(num_grid_points, num_band0, num_band, 6),
order="C",
dtype=self._complex_dtype,
)

View File

@ -0,0 +1,370 @@
"""Wigner thermal conductivity direct solution class."""
# Copyright (C) 2022 Michele Simoncelli
# All rights reserved.
#
# This file is part of phono3py.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# * Neither the name of the phonopy project nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import annotations
import numpy as np
from phonopy.physical_units import get_physical_units
from phono3py.conductivity.direct_solution import (
ConductivityLBTEBase,
diagonalize_collision_matrix,
)
from phono3py.conductivity.wigner_base import (
ConductivityWignerComponents,
get_conversion_factor_WTE,
)
from phono3py.phonon3.interaction import Interaction
class ConductivityWignerLBTE(ConductivityLBTEBase):
"""Class of Wigner lattice thermal conductivity under direct-solution.
Authors
-------
Michele Simoncelli
"""
def __init__(
self,
interaction: Interaction,
grid_points=None,
temperatures=None,
sigmas=None,
sigma_cutoff=None,
is_isotope=False,
mass_variances=None,
boundary_mfp=None,
solve_collective_phonon=False,
is_reducible_collision_matrix=False,
is_kappa_star=True,
gv_delta_q=None,
is_full_pp=False,
read_pp=False,
pp_filename=None,
pinv_cutoff=1.0e-8,
pinv_solver=0,
pinv_method=0,
log_level=0,
lang="C",
):
"""Init method."""
self._kappa_TOT_exact = None
self._kappa_TOT_RTA = None
self._kappa_P_exact = None
self._mode_kappa_P_exact = None
self._kappa_P_RTA = None
self._mode_kappa_P_RTA = None
self._kappa_C = None
self._mode_kappa_C = None
self._gv_operator = None
self._gv_operator_sum2 = None
super().__init__(
interaction,
grid_points=grid_points,
temperatures=temperatures,
sigmas=sigmas,
sigma_cutoff=sigma_cutoff,
is_isotope=is_isotope,
mass_variances=mass_variances,
boundary_mfp=boundary_mfp,
solve_collective_phonon=solve_collective_phonon,
is_reducible_collision_matrix=is_reducible_collision_matrix,
is_kappa_star=is_kappa_star,
is_full_pp=is_full_pp,
read_pp=read_pp,
pp_filename=pp_filename,
pinv_cutoff=pinv_cutoff,
pinv_solver=pinv_solver,
pinv_method=pinv_method,
log_level=log_level,
lang=lang,
)
self._conversion_factor_WTE = get_conversion_factor_WTE(
self._pp.primitive.volume
)
self._conductivity_components = ConductivityWignerComponents(
self._pp,
self._grid_points,
self._grid_weights,
self._point_operations,
self._rotations_cartesian,
temperatures=self._temperatures,
is_kappa_star=self._is_kappa_star,
gv_delta_q=gv_delta_q,
is_reducible_collision_matrix=self._is_reducible_collision_matrix,
log_level=self._log_level,
)
@property
def kappa_TOT_RTA(self):
"""Return kappa."""
return self._kappa_TOT_RTA
@property
def kappa_P_RTA(self):
"""Return kappa."""
return self._kappa_P_RTA
@property
def kappa_C(self):
"""Return kappa."""
return self._kappa_C
@property
def mode_kappa_P_RTA(self):
"""Return mode_kappa."""
return self._mode_kappa_P_RTA
@property
def mode_kappa_C(self):
"""Return mode_kappa."""
return self._mode_kappa_C
@property
def kappa_TOT_exact(self):
"""Return kappa."""
return self._kappa_TOT_exact
@property
def kappa_P_exact(self):
"""Return kappa."""
return self._kappa_P_exact
@property
def mode_kappa_P_exact(self):
"""Return mode_kappa."""
return self._mode_kappa_P_exact
def _set_cv(self, i_gp, i_data):
"""Set cv for conductivity components."""
self._conductivity_components.set_heat_capacities(i_gp, i_data)
def _set_velocities(self, i_gp, i_data):
"""Set velocities for conductivity components."""
self._conductivity_components.set_velocities(i_gp, i_data)
def _allocate_local_values(self, num_grid_points):
"""Allocate grid point local arrays."""
num_band0 = len(self._pp.band_indices)
num_temp = len(self._temperatures)
super()._allocate_local_values(num_grid_points)
nat3 = len(self._pp.primitive) * 3
self._kappa_TOT_RTA = np.zeros(
(len(self._sigmas), num_temp, 6), dtype="double", order="C"
)
self._kappa_TOT_exact = np.zeros(
(len(self._sigmas), num_temp, 6), dtype="double", order="C"
)
self._kappa_P_exact = np.zeros(
(len(self._sigmas), num_temp, 6), dtype="double", order="C"
)
self._kappa_P_RTA = np.zeros(
(len(self._sigmas), num_temp, 6), dtype="double", order="C"
)
self._kappa_C = np.zeros(
(len(self._sigmas), num_temp, 6), dtype="double", order="C"
)
self._mode_kappa_P_exact = np.zeros(
(len(self._sigmas), num_temp, num_grid_points, num_band0, 6), dtype="double"
)
self._mode_kappa_P_RTA = np.zeros(
(len(self._sigmas), num_temp, num_grid_points, num_band0, 6), dtype="double"
)
complex_dtype = "c%d" % (np.dtype("double").itemsize * 2)
# one more index because we have off-diagonal terms (second index not
# parallelized)
self._mode_kappa_C = np.zeros(
(
len(self._sigmas),
num_temp,
num_grid_points,
num_band0,
nat3,
6,
),
order="C",
dtype=complex_dtype,
)
def _set_kappa_at_sigmas(self, weights):
"""Calculate thermal conductivity from collision matrix."""
for j, sigma in enumerate(self._sigmas):
if self._log_level:
text = "----------- Thermal conductivity (W/m-k) "
if sigma:
text += "for sigma=%s -----------" % sigma
else:
text += "with tetrahedron method -----------"
print(text, flush=True)
for k, t in enumerate(self._temperatures):
if t > 0:
self._set_kappa_RTA(j, k, weights)
w = diagonalize_collision_matrix(
self._collision_matrix,
i_sigma=j,
i_temp=k,
pinv_solver=self._pinv_solver,
log_level=self._log_level,
)
self._collision_eigenvalues[j, k] = w
self._set_kappa(j, k, weights)
if self._log_level:
print(
("#%6s " + " %-10s" * 6)
% (
" \t\t T(K)",
"xx",
"yy",
"zz",
"yz",
"xz",
"xy",
)
)
print(
"K_P_exact\t\t"
+ ("%7.1f " + " %10.3f" * 6)
% ((t,) + tuple(self._kappa_P_exact[j, k]))
)
print(
"(K_P_RTA)\t\t"
+ ("%7.1f " + " %10.3f" * 6)
% ((t,) + tuple(self._kappa_P_RTA[j, k]))
)
print(
"K_C \t\t"
+ ("%7.1f " + " %10.3f" * 6)
% ((t,) + tuple(self._kappa_C[j, k].real))
)
print(" ")
print(
"K_TOT=K_P_exact+K_C\t"
+ ("%7.1f " + " %10.3f" * 6)
% (
(t,)
+ tuple(self._kappa_C[j, k] + self._kappa_P_exact[j, k])
)
)
print("-" * 76, flush=True)
if self._log_level:
print("", flush=True)
def _set_kappa(self, i_sigma, i_temp, weights):
if self._is_reducible_collision_matrix:
self._set_kappa_reducible_colmat(
self._kappa_P_exact, self._mode_kappa_P_exact, i_sigma, i_temp, weights
)
else:
self._set_kappa_ir_colmat(
self._kappa_P_exact, self._mode_kappa_P_exact, i_sigma, i_temp, weights
)
def _set_kappa_RTA(self, i_sigma, i_temp, weights):
if self._is_reducible_collision_matrix:
self._set_kappa_RTA_reducible_colmat(
self._kappa_P_RTA, self._mode_kappa_P_RTA, i_sigma, i_temp, weights
)
print(
" WARNING: Coherences conductivity not implemented for "
"is_reducible_collision_matrix=True "
)
else:
self._set_kappa_RTA_ir_colmat(
self._kappa_P_RTA, self._mode_kappa_P_RTA, i_sigma, i_temp, weights
)
self._set_kappa_C_ir_colmat(i_sigma, i_temp)
def _set_kappa_C_ir_colmat(self, i_sigma, i_temp):
"""Calculate coherence term of the thermal conductivity."""
N = self.number_of_sampling_grid_points
num_band = len(self._pp.primitive) * 3
# num_ir_grid_points = len(self._ir_grid_points)
THzToEv = get_physical_units().THzToEv
for i, gp in enumerate(self._ir_grid_points):
# linewidths at qpoint i, sigma i_sigma, and temperature i_temp
g = self._get_main_diagonal(i, i_sigma, i_temp) * 2.0 # linewidth (FWHM)
frequencies = self._frequencies[gp]
cv = self._conductivity_components.mode_heat_capacities[i_temp, i, :]
for s1 in range(num_band):
for s2 in range(num_band):
hbar_omega_eV_s1 = (
frequencies[s1] * THzToEv
) # hbar*omega=h*nu in eV
hbar_omega_eV_s2 = (
frequencies[s2] * THzToEv
) # hbar*omega=h*nu in eV
if (
(frequencies[s1] > self._pp.cutoff_frequency)
and (frequencies[s2] > self._pp.cutoff_frequency)
) and np.abs(frequencies[s1] - frequencies[s2]) > 1e-4:
# frequencies must be non-degenerate to contribute to k_C,
# otherwise they contribute to k_P
hbar_gamma_eV_s1 = g[s1] * THzToEv
hbar_gamma_eV_s2 = g[s2] * THzToEv
lorentzian_divided_by_hbar = (
0.5 * (hbar_gamma_eV_s1 + hbar_gamma_eV_s2)
) / (
(hbar_omega_eV_s1 - hbar_omega_eV_s2) ** 2
+ 0.25 * ((hbar_gamma_eV_s1 + hbar_gamma_eV_s2) ** 2)
)
#
prefactor = (
0.25
* (hbar_omega_eV_s1 + hbar_omega_eV_s2)
* (cv[s1] / hbar_omega_eV_s1 + cv[s2] / hbar_omega_eV_s2)
)
self._mode_kappa_C[i_sigma, i_temp, i, s1, s2] = (
(self._conductivity_components.gv_by_gv_operator[i, s1, s2])
* prefactor
* lorentzian_divided_by_hbar
* self._conversion_factor_WTE
)
self._kappa_C[i_sigma, i_temp] = (
self._mode_kappa_C[i_sigma, i_temp].sum(axis=0).sum(axis=0).sum(axis=0) / N
).real

View File

@ -0,0 +1,288 @@
"""Wigner thermal conductivity RTA class."""
# Copyright (C) 2022 Michele Simoncelli
# All rights reserved.
#
# This file is part of phono3py.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# * Neither the name of the phonopy project nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import annotations
import numpy as np
from phonopy.physical_units import get_physical_units
from phono3py.conductivity.rta_base import ConductivityRTABase
from phono3py.conductivity.wigner_base import (
ConductivityWignerComponents,
get_conversion_factor_WTE,
)
from phono3py.phonon3.interaction import Interaction
class ConductivityWignerRTA(ConductivityRTABase):
"""Class of Wigner lattice thermal conductivity under RTA.
Authors
-------
Michele Simoncelli
"""
def __init__(
self,
interaction: Interaction,
grid_points: np.ndarray | None = None,
temperatures: list | np.ndarray | None = None,
sigmas: list | np.ndarray | None = None,
sigma_cutoff: float | None = None,
is_isotope: bool = False,
mass_variances: list | np.ndarray | None = None,
boundary_mfp: float | None = None, # in micrometer
use_ave_pp: bool = False,
is_kappa_star: bool = True,
gv_delta_q: float | None = None,
is_full_pp: bool = False,
read_pp: bool = False,
store_pp: bool = False,
pp_filename: float | None = None,
is_N_U: bool = False,
is_gamma_detail: bool = False,
is_frequency_shift_by_bubble: bool = False,
log_level: int = 0,
):
"""Init method."""
self._cv = None
self._kappa_TOT_RTA = None
self._kappa_P_RTA = None
self._kappa_C = None
self._mode_kappa_P_RTA = None
self._mode_kappa_C = None
self._gv_operator = None
self._gv_operator_sum2 = None
super().__init__(
interaction,
grid_points=grid_points,
temperatures=temperatures,
sigmas=sigmas,
sigma_cutoff=sigma_cutoff,
is_isotope=is_isotope,
mass_variances=mass_variances,
boundary_mfp=boundary_mfp,
use_ave_pp=use_ave_pp,
is_kappa_star=is_kappa_star,
is_full_pp=is_full_pp,
read_pp=read_pp,
store_pp=store_pp,
pp_filename=pp_filename,
is_N_U=is_N_U,
is_gamma_detail=is_gamma_detail,
is_frequency_shift_by_bubble=is_frequency_shift_by_bubble,
log_level=log_level,
)
self._conversion_factor_WTE = get_conversion_factor_WTE(
self._pp.primitive.volume
)
self._conductivity_components = ConductivityWignerComponents(
self._pp,
self._grid_points,
self._grid_weights,
self._point_operations,
self._rotations_cartesian,
temperatures=self._temperatures,
is_kappa_star=self._is_kappa_star,
gv_delta_q=gv_delta_q,
log_level=self._log_level,
)
@property
def kappa_TOT_RTA(self):
"""Return kappa."""
return self._kappa_TOT_RTA
@property
def kappa_P_RTA(self):
"""Return kappa."""
return self._kappa_P_RTA
@property
def kappa_C(self):
"""Return kappa."""
return self._kappa_C
@property
def mode_kappa_P_RTA(self):
"""Return mode_kappa."""
return self._mode_kappa_P_RTA
@property
def mode_kappa_C(self):
"""Return mode_kappa."""
return self._mode_kappa_C
def set_kappa_at_sigmas(self):
"""Calculate the Wigner thermal conductivity.
k_P + k_C using the scattering operator in the RTA approximation.
"""
num_band = len(self._pp.primitive) * 3
THzToEv = get_physical_units().THzToEv
gv_by_gv = self._conductivity_components.gv_by_gv_operator
cv = self._conductivity_components.mode_heat_capacities
for i, _ in enumerate(self._grid_points):
gp = self._grid_points[i]
frequencies = self._frequencies[gp]
# Kappa
for j in range(len(self._sigmas)):
for k in range(len(self._temperatures)):
g_sum = self._get_main_diagonal(
i, j, k
) # phonon HWHM: q-point, sigma, temperature
for s1 in range(num_band):
for s2 in range(num_band):
hbar_omega_eV_s1 = (
frequencies[s1] * THzToEv
) # hbar*omega=h*nu in eV
hbar_omega_eV_s2 = (
frequencies[s2] * THzToEv
) # hbar*omega=h*nu in eV
if (frequencies[s1] > self._pp.cutoff_frequency) and (
frequencies[s2] > self._pp.cutoff_frequency
):
hbar_gamma_eV_s1 = 2.0 * g_sum[s1] * THzToEv
hbar_gamma_eV_s2 = 2.0 * g_sum[s2] * THzToEv
#
lorentzian_divided_by_hbar = (
0.5 * (hbar_gamma_eV_s1 + hbar_gamma_eV_s2)
) / (
(hbar_omega_eV_s1 - hbar_omega_eV_s2) ** 2
+ 0.25
* ((hbar_gamma_eV_s1 + hbar_gamma_eV_s2) ** 2)
)
#
prefactor = (
0.25
* (hbar_omega_eV_s1 + hbar_omega_eV_s2)
* (
cv[k, i, s1] / hbar_omega_eV_s1
+ cv[k, i, s2] / hbar_omega_eV_s2
)
)
if np.abs(frequencies[s1] - frequencies[s2]) < 1e-4:
# degenerate or diagonal s1=s2 modes contribution
# determine k_P
contribution = (
(gv_by_gv[i, s1, s2])
* prefactor
* lorentzian_divided_by_hbar
* self._conversion_factor_WTE
).real
#
self._mode_kappa_P_RTA[j, k, i, s1] += (
0.5 * contribution
)
self._mode_kappa_P_RTA[j, k, i, s2] += (
0.5 * contribution
)
# prefactor 0.5 arises from the fact that degenerate
# modes have the same specific heat, hence they give
# the same contribution to the populations
# conductivity
else:
self._mode_kappa_C[j, k, i, s1, s2] += (
(gv_by_gv[i, s1, s2])
* prefactor
* lorentzian_divided_by_hbar
* self._conversion_factor_WTE
).real
elif s1 == s2:
self._num_ignored_phonon_modes[j, k] += 1
N = self.number_of_sampling_grid_points
self._kappa_P_RTA = self._mode_kappa_P_RTA.sum(axis=2).sum(axis=2) / N
#
self._kappa_C = self._mode_kappa_C.sum(axis=2).sum(axis=2).sum(axis=2) / N
#
self._kappa_TOT_RTA = self._kappa_P_RTA + self._kappa_C
def _set_cv(self, i_gp, i_data):
"""Set cv for conductivity components."""
self._conductivity_components.set_heat_capacities(i_gp, i_data)
def _set_velocities(self, i_gp, i_data):
"""Set velocities for conductivity components."""
self._conductivity_components.set_velocities(i_gp, i_data)
def _allocate_values(self):
super()._allocate_values()
num_band0 = len(self._pp.band_indices)
num_grid_points = len(self._grid_points)
num_temp = len(self._temperatures)
nat3 = len(self._pp.primitive) * 3
# kappa* and mode_kappa* are accessed when all bands exist, i.e.,
# num_band0==num_band.
self._kappa_TOT_RTA = np.zeros(
(len(self._sigmas), num_temp, 6), order="C", dtype="double"
)
self._kappa_P_RTA = np.zeros(
(len(self._sigmas), num_temp, 6), order="C", dtype="double"
)
self._kappa_C = np.zeros(
(len(self._sigmas), num_temp, 6), order="C", dtype="double"
)
self._mode_kappa_P_RTA = np.zeros(
(len(self._sigmas), num_temp, num_grid_points, nat3, 6),
order="C",
dtype="double",
)
# one more index because we have off-diagonal terms (second index not
# parallelized)
self._mode_kappa_C = np.zeros(
(
len(self._sigmas),
num_temp,
num_grid_points,
num_band0,
nat3,
6,
),
order="C",
dtype="double",
)

View File

@ -37,198 +37,40 @@
from __future__ import annotations
import copy
import dataclasses
import os
import pathlib
import sys
from dataclasses import asdict
from typing import Literal, Optional, Union
from typing import Literal, cast
import numpy as np
from phonopy.cui.phonopy_script import file_exists, print_error
from phonopy.file_IO import get_dataset_type2
from phonopy.harmonic.force_constants import (
show_drift_force_constants,
symmetrize_compact_force_constants,
symmetrize_force_constants,
from phonopy import Phonopy
from phonopy.cui.load_helper import (
develop_or_load_pypolymlp as develop_or_load_pypolymlp_phonopy,
)
from phonopy.interface.calculator import get_default_physical_units
from phonopy.interface.fc_calculator import fc_calculator_names
from phonopy.file_IO import get_dataset_type2
from phonopy.interface.calculator import get_calculator_physical_units
from phonopy.interface.pypolymlp import PypolymlpParams, parse_mlp_params
from phonopy.interface.symfc import parse_symfc_options
from phono3py import Phono3py
from phono3py.cui.settings import Phono3pySettings
from phono3py.cui.show_log import show_phono3py_force_constants_settings
from phono3py.file_IO import (
get_length_of_first_line,
parse_FORCES_FC2,
parse_FORCES_FC3,
read_fc2_from_hdf5,
read_fc3_from_hdf5,
write_fc2_to_hdf5,
write_fc3_to_hdf5,
)
from phono3py.interface.fc_calculator import extract_fc2_fc3_calculators
from phono3py.interface.fc_calculator import determine_cutoff_pair_distance
from phono3py.interface.phono3py_yaml import Phono3pyYaml
from phono3py.phonon3.dataset import forces_in_dataset
from phono3py.phonon3.fc3 import (
set_permutation_symmetry_fc3,
set_translational_invariance_fc3,
show_drift_fc3,
)
def get_cutoff_pair_distance(settings: Phono3pySettings) -> Optional[float]:
"""Return cutoff_pair_distance from settings."""
_, fc_calculator_options = get_fc_calculator_params(settings)
if settings.cutoff_pair_distance is None:
cutoff = parse_symfc_options(
extract_fc2_fc3_calculators(fc_calculator_options, 3)
).get("cutoff")
if cutoff is None:
cutoff_pair_distance = None
else:
cutoff_pair_distance = cutoff.get(3)
else:
cutoff_pair_distance = settings.cutoff_pair_distance
return cutoff_pair_distance
def create_phono3py_force_constants(
phono3py: Phono3py,
settings,
ph3py_yaml: Optional[Phono3pyYaml] = None,
phono3py_yaml_filename: Optional[str] = None,
calculator: Optional[str] = None,
input_filename: Optional[str] = None,
output_filename: Optional[str] = None,
log_level=1,
):
"""Read or calculate force constants.
This function is for the 'phonopy' command only and not for the
'phonopy-load' command.
"""
# Only for build-in fc calculator.
# These are not applied to external fc calculators.
symmetrize_fc3r = settings.is_symmetrize_fc3_r or settings.fc_symmetry
symmetrize_fc2 = settings.is_symmetrize_fc2 or settings.fc_symmetry
if log_level:
show_phono3py_force_constants_settings(settings)
#######
# fc3 #
#######
if (
settings.is_joint_dos
or (settings.is_isotope and not (settings.is_bterta or settings.is_lbte))
or settings.read_gamma
or settings.read_pp
or (not settings.is_bterta and settings.write_phonon)
or settings.constant_averaged_pp_interaction is not None
):
pass
else:
(fc_calculator, fc_calculator_options) = get_fc_calculator_params(
settings, log_level=(not settings.read_fc3) * 1
)
if settings.read_fc3:
_read_phono3py_fc3(phono3py, symmetrize_fc3r, input_filename, log_level)
else: # fc3 from FORCES_FC3 or ph3py_yaml
dataset = _read_dataset_fc3(
phono3py,
ph3py_yaml,
phono3py_yaml_filename,
settings.cutoff_pair_distance,
calculator,
log_level,
)
phono3py.dataset = dataset
phono3py.produce_fc3(
symmetrize_fc3r=symmetrize_fc3r,
is_compact_fc=settings.is_compact_fc,
fc_calculator=extract_fc2_fc3_calculators(fc_calculator, 3),
fc_calculator_options=extract_fc2_fc3_calculators(
fc_calculator_options, 3
),
)
cutoff_distance = settings.cutoff_fc3_distance
if cutoff_distance is not None and cutoff_distance > 0:
if log_level:
print(
"Cutting-off fc3 by zero (cut-off distance: %f)" % cutoff_distance
)
phono3py.cutoff_fc3_by_zero(cutoff_distance)
if not settings.read_fc3:
if output_filename is None:
filename = "fc3.hdf5"
else:
filename = "fc3." + output_filename + ".hdf5"
if log_level:
print('Writing fc3 to "%s".' % filename)
write_fc3_to_hdf5(
phono3py.fc3,
filename=filename,
p2s_map=phono3py.primitive.p2s_map,
compression=settings.hdf5_compression,
)
if log_level:
show_drift_fc3(phono3py.fc3, primitive=phono3py.primitive)
#######
# fc2 #
#######
phonon_primitive = phono3py.phonon_primitive
p2s_map = phonon_primitive.p2s_map
if settings.read_fc2:
_read_phono3py_fc2(phono3py, symmetrize_fc2, input_filename, log_level)
else:
if phono3py.dataset is None or phono3py.phonon_supercell_matrix is not None:
_read_dataset_fc2(
phono3py,
ph3py_yaml,
calculator,
log_level,
)
phono3py.produce_fc2(
symmetrize_fc2=symmetrize_fc2,
is_compact_fc=settings.is_compact_fc,
fc_calculator=extract_fc2_fc3_calculators(fc_calculator, 2),
fc_calculator_options=extract_fc2_fc3_calculators(fc_calculator_options, 2),
)
if output_filename is None:
filename = "fc2.hdf5"
else:
filename = "fc2." + output_filename + ".hdf5"
if log_level:
print('Writing fc2 to "%s".' % filename)
write_fc2_to_hdf5(
phono3py.fc2,
filename=filename,
p2s_map=p2s_map,
physical_unit="eV/angstrom^2",
compression=settings.hdf5_compression,
)
if log_level:
show_drift_force_constants(phono3py.fc2, primitive=phonon_primitive, name="fc2")
def parse_forces(
phono3py: Phono3py,
ph3py_yaml: Optional[Phono3pyYaml] = None,
cutoff_pair_distance=None,
force_filename: str = "FORCES_FC3",
phono3py_yaml_filename: Optional[str] = None,
ph3py_yaml: Phono3pyYaml | None = None,
cutoff_pair_distance: float | None = None,
force_filename: str | os.PathLike = "FORCES_FC3",
phono3py_yaml_filename: str | os.PathLike | None = None,
fc_type: Literal["fc3", "phonon_fc2"] = "fc3",
calculator: Optional[str] = None,
log_level=0,
calculator: str | None = None,
log_level: int = 0,
) -> dict:
"""Read displacements and forces.
@ -239,7 +81,7 @@ def parse_forces(
without writing calculator name in it.
"""
filename_read_from: Optional[str] = None
filename_read_from = None
dataset = None
if phono3py.phonon_supercell is None or fc_type == "fc3":
@ -254,7 +96,7 @@ def parse_forces(
if dataset:
filename_read_from = phono3py_yaml_filename
physical_units = get_default_physical_units(calculator)
physical_units = get_calculator_physical_units(calculator)
# Forces are not yet found in dataset. Then try to read from FORCES_FC3 or
# FORCES_FC2.
@ -266,15 +108,17 @@ def parse_forces(
if dataset:
filename_read_from = force_filename
if dataset is None:
raise RuntimeError("Dataset is not found.")
# Units of displacements and forces are converted. If forces don't
# exist, the convesion will not be performed for forces.
# exist, the conversion will not be performed for forces.
if calculator is not None:
_convert_unit_in_dataset(
dataset,
distance_to_A=physical_units["distance_to_A"],
force_to_eVperA=physical_units["force_to_eVperA"],
)
assert dataset is not None
if "natom" in dataset and dataset["natom"] != natom:
raise RuntimeError(
@ -306,140 +150,13 @@ def parse_forces(
return dataset
def get_fc_calculator_params(
settings: Phono3pySettings, log_level: int = 0
) -> tuple[Optional[str], Optional[str]]:
"""Return fc_calculator and fc_calculator_params from settings."""
fc_calculator = None
fc_calculator_list = []
if settings.fc_calculator is not None:
for fc_calculatr_str in settings.fc_calculator.split("|"):
if fc_calculatr_str == "": # No external calculator
fc_calculator_list.append(fc_calculatr_str.lower())
elif fc_calculatr_str.lower() in fc_calculator_names:
fc_calculator_list.append(fc_calculatr_str.lower())
if fc_calculator_list:
fc_calculator = "|".join(fc_calculator_list)
fc_calculator_options = settings.fc_calculator_options
if settings.cutoff_pair_distance:
if fc_calculator_list and fc_calculator_list[-1] in ("alm", "symfc"):
if fc_calculator_list[-1] == "alm":
cutoff_str = f"-1 {settings.cutoff_pair_distance}"
if fc_calculator_list[-1] == "symfc":
cutoff_str = f"{settings.cutoff_pair_distance}"
fc_calculator_options = _set_cutoff_in_fc_calculator_options(
fc_calculator_options,
cutoff_str,
log_level,
)
return fc_calculator, fc_calculator_options
def _set_cutoff_in_fc_calculator_options(
fc_calculator_options: Optional[str],
cutoff_str: str,
log_level: int,
):
str_appended = f"cutoff={cutoff_str}"
calc_opts = fc_calculator_options
if calc_opts is None:
calc_opts = "|"
if "|" in calc_opts:
calc_opts_fc2, calc_opts_fc3 = [v.strip() for v in calc_opts.split("|")][:2]
else:
calc_opts_fc2 = calc_opts
calc_opts_fc3 = calc_opts
if calc_opts_fc3 == "":
calc_opts_fc3 += f"{str_appended}"
if log_level:
print(f'Set "{str_appended}" to fc_calculator_options for fc3.')
elif "cutoff" not in calc_opts_fc3:
calc_opts_fc3 += f", {str_appended}"
if log_level:
print(f'Appended "{str_appended}" to fc_calculator_options for fc3.')
return f"{calc_opts_fc2}|{calc_opts_fc3}"
def _read_phono3py_fc3(phono3py: Phono3py, symmetrize_fc3r, input_filename, log_level):
if input_filename is None:
filename = "fc3.hdf5"
else:
filename = "fc3." + input_filename + ".hdf5"
file_exists(filename, log_level=log_level)
if log_level:
print('Reading fc3 from "%s".' % filename)
p2s_map = phono3py.primitive.p2s_map
try:
fc3 = read_fc3_from_hdf5(filename=filename, p2s_map=p2s_map)
except RuntimeError:
import traceback
traceback.print_exc()
if log_level:
print_error()
sys.exit(1)
num_atom = len(phono3py.supercell)
if fc3.shape[1] != num_atom:
print("Matrix shape of fc3 doesn't agree with supercell size.")
if log_level:
print_error()
sys.exit(1)
if symmetrize_fc3r:
set_translational_invariance_fc3(fc3)
set_permutation_symmetry_fc3(fc3)
phono3py.fc3 = fc3
def _read_phono3py_fc2(phono3py, symmetrize_fc2, input_filename, log_level):
if input_filename is None:
filename = "fc2.hdf5"
else:
filename = "fc2." + input_filename + ".hdf5"
file_exists(filename, log_level=log_level)
if log_level:
print('Reading fc2 from "%s".' % filename)
num_atom = len(phono3py.phonon_supercell)
p2s_map = phono3py.phonon_primitive.p2s_map
try:
phonon_fc2 = read_fc2_from_hdf5(filename=filename, p2s_map=p2s_map)
except RuntimeError:
import traceback
traceback.print_exc()
if log_level:
print_error()
sys.exit(1)
if phonon_fc2.shape[1] != num_atom:
print("Matrix shape of fc2 doesn't agree with supercell size.")
if log_level:
print_error()
sys.exit(1)
if symmetrize_fc2:
if phonon_fc2.shape[0] == phonon_fc2.shape[1]:
symmetrize_force_constants(phonon_fc2)
else:
symmetrize_compact_force_constants(phonon_fc2, phono3py.phonon_primitive)
phono3py.fc2 = phonon_fc2
def _read_FORCES_FC3_or_FC2(
natom: int,
dataset: Optional[dict],
dataset: dict | None,
fc_type: str,
filename: str = "FORCES_FC3",
filename: str | os.PathLike = "FORCES_FC3",
log_level: int = 0,
) -> Optional[dict]:
) -> dict | None:
"""Read FORCES_FC3 or FORCES_FC2.
Read the first line of forces file to determine the type of the file.
@ -457,7 +174,9 @@ def _read_FORCES_FC3_or_FC2(
print(f'{n_disp} snapshots were found in "{filename}".')
return _dataset
# Type-1
# Try reading type-1 dataset
if dataset is None:
raise RuntimeError("Type-1 displacement dataset is not given.")
if fc_type == "fc3":
parse_FORCES_FC3(dataset, filename)
else:
@ -470,154 +189,108 @@ def _read_FORCES_FC3_or_FC2(
return dataset
def _read_dataset_fc3(
phono3py: Phono3py,
ph3py_yaml: Optional[Phono3pyYaml],
phono3py_yaml_filename: Optional[str],
cutoff_pair_distance: Optional[float],
calculator: Optional[str],
log_level: int,
) -> dict:
"""Read or calculate fc3.
Note
----
cutoff_pair_distance is the parameter to determine each displaced
supercell is included to the computation of fc3. It is assumed that
cutoff_pair_distance is stored in the step to create sets of
displacements and the value is stored n the displacement dataset and
also as the parameter 'included': True or False for each displacement.
The parameter cutoff_pair_distance here can be used in the step to
create fc3 by overwriting original cutoff_pair_distance value only
when the former value is smaller than the later.
"""
try:
dataset = parse_forces(
phono3py,
ph3py_yaml=ph3py_yaml,
cutoff_pair_distance=cutoff_pair_distance,
force_filename="FORCES_FC3",
phono3py_yaml_filename=phono3py_yaml_filename,
fc_type="fc3",
calculator=calculator,
log_level=log_level,
)
except RuntimeError as e:
# from _parse_forces_type1
if log_level:
print(str(e))
print_error()
sys.exit(1)
except FileNotFoundError as e:
# from _get_type2_dataset
file_exists(e.filename, log_level=log_level)
return dataset
def run_pypolymlp_to_compute_forces(
def develop_or_load_pypolymlp(
ph3py: Phono3py,
mlp_params: Union[str, dict, PypolymlpParams],
displacement_distance: Optional[float] = None,
number_of_snapshots: Optional[int] = None,
random_seed: Optional[int] = None,
prepare_dataset: bool = False,
cutoff_pair_distance: Optional[float] = None,
mlp_filename: str = "phono3py.pmlp",
mlp_params: str | dict | PypolymlpParams | None = None,
mlp_filename: str | os.PathLike | None = None,
log_level: int = 0,
):
"""Run pypolymlp to compute forces."""
if log_level:
print("-" * 29 + " pypolymlp start " + "-" * 30)
print("Pypolymlp is a generator of polynomial machine learning potentials.")
print("Please cite the paper: A. Seko, J. Appl. Phys. 133, 011101 (2023).")
print("Pypolymlp is developed at https://github.com/sekocha/pypolymlp.")
develop_or_load_pypolymlp_phonopy(
cast(Phonopy, ph3py),
mlp_params=mlp_params,
mlp_filename=mlp_filename,
log_level=log_level,
)
if pathlib.Path(mlp_filename).exists():
if log_level:
print(f'Load MLPs from "{mlp_filename}".')
ph3py.load_mlp(mlp_filename)
elif forces_in_dataset(ph3py.mlp_dataset):
if log_level:
if mlp_params is None:
pmlp_params = PypolymlpParams()
else:
pmlp_params = parse_mlp_params(mlp_params)
print("Parameters:")
for k, v in asdict(pmlp_params).items():
if v is not None:
print(f" {k}: {v}")
print("Developing MLPs by pypolymlp...", flush=True)
ph3py.develop_mlp(params=mlp_params)
ph3py.save_mlp(filename=mlp_filename)
if log_level:
print(f'MLPs were written into "{mlp_filename}"', flush=True)
def generate_displacements_and_evaluate_pypolymlp(
ph3py: Phono3py,
displacement_distance: float | None = None,
number_of_snapshots: int | Literal["auto"] | None = None,
number_estimation_factor: int | None = None,
random_seed: int | None = None,
fc_calculator: str | None = None,
fc_calculator_options: str | None = None,
cutoff_pair_distance: float | None = None,
symfc_memory_size: float | None = None,
log_level: int = 0,
):
"""Generate displacements and evaluate forces by pypolymlp."""
if displacement_distance is None:
_displacement_distance = 0.01
else:
raise RuntimeError(f'"{mlp_filename}" is not found.')
_displacement_distance = displacement_distance
if log_level:
print("-" * 30 + " pypolymlp end " + "-" * 31, flush=True)
if prepare_dataset:
if displacement_distance is None:
_displacement_distance = 0.01
else:
_displacement_distance = displacement_distance
if log_level:
if number_of_snapshots:
print("Generate random displacements")
print(
" Twice of number of snapshots will be generated "
"for plus-minus displacements."
)
else:
print("Generate displacements")
if number_of_snapshots:
print("Generate random displacements")
print(
f" Displacement distance: {_displacement_distance:.5f}".rstrip(
"0"
).rstrip(".")
" Twice of number of snapshots will be generated "
"for plus-minus displacements."
)
else:
print("Generate displacements")
print(
f" Displacement distance: {_displacement_distance:.5f}".rstrip("0").rstrip(
"."
)
ph3py.generate_displacements(
distance=_displacement_distance,
cutoff_pair_distance=cutoff_pair_distance,
is_plusminus=True,
number_of_snapshots=number_of_snapshots,
random_seed=random_seed,
)
if log_level:
print(
f"Evaluate forces in {ph3py.displacements.shape[0]} supercells "
"by pypolymlp",
flush=True,
)
cutoff_pair_distance = determine_cutoff_pair_distance(
fc_calculator=fc_calculator,
fc_calculator_options=fc_calculator_options,
cutoff_pair_distance=cutoff_pair_distance,
symfc_memory_size=symfc_memory_size,
random_displacements=number_of_snapshots,
supercell=ph3py.supercell,
primitive=ph3py.primitive,
symmetry=ph3py.symmetry,
log_level=log_level,
)
ph3py.generate_displacements(
distance=_displacement_distance,
cutoff_pair_distance=cutoff_pair_distance,
is_plusminus=True,
number_of_snapshots=number_of_snapshots,
random_seed=random_seed,
number_estimation_factor=number_estimation_factor,
)
if ph3py.supercells_with_displacements is None:
raise RuntimeError("Displacements are not set. Run generate_displacements.")
if log_level:
print(
f"Evaluate forces in {ph3py.displacements.shape[0]} supercells "
"by pypolymlp",
flush=True,
)
ph3py.evaluate_mlp()
if ph3py.supercells_with_displacements is None:
raise RuntimeError("Displacements are not set. Run generate_displacements.")
ph3py.evaluate_mlp()
def run_pypolymlp_to_compute_phonon_forces(
ph3py: Phono3py,
mlp_params: Optional[Union[str, dict, PypolymlpParams]] = None,
displacement_distance: Optional[float] = None,
number_of_snapshots: Optional[int] = None,
random_seed: Optional[int] = None,
mlp_params: str | dict | PypolymlpParams | None = None,
displacement_distance: float | None = None,
number_of_snapshots: int | None = None,
random_seed: int | None = None,
log_level: int = 0,
):
"""Run pypolymlp to compute phonon forces."""
if ph3py.phonon_mlp_dataset is not None:
if log_level:
import pypolymlp
print("-" * 29 + " pypolymlp start " + "-" * 30)
print(f"Pypolymlp version {pypolymlp.__version__}")
print("Pypolymlp is a generator of polynomial machine learning potentials.")
print("Please cite the paper: A. Seko, J. Appl. Phys. 133, 011101 (2023).")
print("Pypolymlp is developed at https://github.com/sekocha/pypolymlp.")
if mlp_params:
print("Parameters:")
for k, v in asdict(parse_mlp_params(mlp_params)).items():
for k, v in dataclasses.asdict(parse_mlp_params(mlp_params)).items():
if v is not None:
print(f" {k}: {v}")
if log_level:
@ -654,61 +327,10 @@ def run_pypolymlp_to_compute_phonon_forces(
ph3py.evaluate_phonon_mlp()
def _read_dataset_fc2(
phono3py: Phono3py,
ph3py_yaml: Optional[Phono3pyYaml],
calculator,
log_level,
):
"""Read forces and produce fc2.
force_filename is either "FORCES_FC2" or "FORCES_FC3".
"""
# _ph3py_yaml = _get_default_ph3py_yaml(ph3py_yaml)
if phono3py.phonon_supercell_matrix is not None:
force_filename = "FORCES_FC2"
elif phono3py.dataset is None:
force_filename = "FORCES_FC3"
else:
raise RuntimeError("Force filename is not determined.")
try:
dataset = parse_forces(
phono3py,
ph3py_yaml=ph3py_yaml,
force_filename=force_filename,
fc_type="phonon_fc2",
calculator=calculator,
log_level=log_level,
)
except RuntimeError as e:
if log_level:
print(str(e))
print_error()
sys.exit(1)
except FileNotFoundError as e:
file_exists(e.filename, log_level=log_level)
if phono3py.phonon_supercell_matrix is not None:
phono3py.phonon_dataset = dataset
elif phono3py.dataset is None:
phono3py.dataset = dataset
def _get_default_ph3py_yaml(ph3py_yaml: Optional[Phono3pyYaml]):
_ph3py_yaml = ph3py_yaml
if _ph3py_yaml is None and pathlib.Path("phono3py_disp.yaml").exists():
_ph3py_yaml = Phono3pyYaml()
_ph3py_yaml.read("phono3py_disp.yaml")
return _ph3py_yaml
def _convert_unit_in_dataset(
dataset: dict,
distance_to_A: Optional[float] = None,
force_to_eVperA: Optional[float] = None,
distance_to_A: float | None = None,
force_to_eVperA: float | None = None,
) -> None:
"""Convert physical units of displacements and forces in dataset.
@ -747,9 +369,7 @@ def _to_ndarray(array, dtype="double"):
return array
def _extract_dataset_from_ph3py_yaml(
ph3py_yaml: Optional[Phono3pyYaml], fc_type
) -> Optional[dict]:
def _extract_dataset_from_ph3py_yaml(ph3py_yaml: Phono3pyYaml, fc_type) -> dict | None:
if ph3py_yaml.phonon_supercell is None or fc_type == "fc3":
if ph3py_yaml.dataset is not None:
return copy.deepcopy(ph3py_yaml.dataset)

View File

@ -200,17 +200,15 @@ def create_FORCES_FC2_from_FORCE_SETS(log_level):
def create_FORCE_SETS_from_FORCES_FCx(
phonon_smat, input_filename: Optional[str], cell_filename: Optional[str], log_level
phonon_smat, cell_filename: Optional[str], log_level
):
"""Convert FORCES_FC3 or FORCES_FC2 to FORCE_SETS."""
if cell_filename is not None and is_file_phonopy_yaml(
cell_filename, keyword="phono3py"
):
disp_filename = cell_filename
elif input_filename is None:
disp_filename = "phono3py_disp.yaml"
else:
disp_filename = f"phono3py_disp.{input_filename}.yaml"
disp_filename = "phono3py_disp.yaml"
if phonon_smat is not None:
forces_filename = "FORCES_FC2"
else:
@ -477,9 +475,10 @@ def _set_forces_and_nac_params(
ph3py_yaml.dataset["forces"] = np.array(
calc_dataset_fc3["forces"], dtype="double", order="C"
)
ph3py_yaml.dataset["supercell_energies"] = np.array(
calc_dataset_fc3["supercell_energies"], dtype="double"
)
if "supercell_energies" in calc_dataset_fc3:
ph3py_yaml.dataset["supercell_energies"] = np.array(
calc_dataset_fc3["supercell_energies"], dtype="double"
)
if len(ph3py_yaml.dataset["forces"]) != len(
ph3py_yaml.dataset["displacements"]
):
@ -499,9 +498,10 @@ def _set_forces_and_nac_params(
ph3py_yaml.phonon_dataset["forces"] = np.array(
calc_dataset_fc2["forces"], dtype="double", order="C"
)
ph3py_yaml.phonon_dataset["supercell_energies"] = np.array(
calc_dataset_fc2["supercell_energies"], dtype="double"
)
if "supercell_energies" in calc_dataset_fc2:
ph3py_yaml.phonon_dataset["supercell_energies"] = np.array(
calc_dataset_fc2["supercell_energies"], dtype="double"
)
if len(ph3py_yaml.phonon_dataset["forces"]) != len(
ph3py_yaml.phonon_dataset["displacements"]
):

View File

@ -34,98 +34,161 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import annotations
import dataclasses
import os
import numpy as np
from numpy.typing import ArrayLike
from phonopy.cui.collect_cell_info import CellInfoResult
from phonopy.cui.collect_cell_info import get_cell_info as phonopy_get_cell_info
from phonopy.interface.calculator import write_supercells_with_displacements
from phonopy.structure.cells import print_cell
from phono3py import Phono3py
from phono3py.cui.settings import Phono3pySettings
from phono3py.cui.show_log import print_supercell_matrix
from phono3py.interface.calculator import (
get_additional_info_to_write_fc2_supercells,
get_additional_info_to_write_supercells,
get_default_displacement_distance,
)
from phono3py.interface.fc_calculator import determine_cutoff_pair_distance
from phono3py.interface.phono3py_yaml import Phono3pyYaml
@dataclasses.dataclass
class Phono3pyCellInfoResult(CellInfoResult):
"""Phono3py cell info result.
This is a subclass of CellInfoResult to add phonon supercell matrix.
"""
phono3py_yaml: Phono3pyYaml | None = None
phonon_supercell_matrix: ArrayLike | None = None
def get_cell_info(
settings: Phono3pySettings,
cell_filename: str | os.PathLike | None,
log_level: int,
load_phonopy_yaml: bool = True,
) -> Phono3pyCellInfoResult:
"""Return calculator interface and crystal structure information."""
cell_info = phonopy_get_cell_info(
settings,
cell_filename,
log_level=log_level,
load_phonopy_yaml=load_phonopy_yaml,
phonopy_yaml_cls=Phono3pyYaml,
)
cell_info_dict = dataclasses.asdict(cell_info)
cell_info_dict["phono3py_yaml"] = cell_info_dict.pop("phonopy_yaml")
cell_info = Phono3pyCellInfoResult(
**cell_info_dict,
phonon_supercell_matrix=settings.phonon_supercell_matrix,
)
ph3py_yaml = cell_info.phono3py_yaml
if cell_info.phonon_supercell_matrix is None and ph3py_yaml:
cell_info.phonon_supercell_matrix = ph3py_yaml.phonon_supercell_matrix
return cell_info
def create_phono3py_supercells(
cell_info,
settings,
symprec,
interface_mode="vasp",
log_level=1,
cell_info: Phono3pyCellInfoResult,
settings: Phono3pySettings,
symprec: float,
interface_mode: str | None = "vasp",
log_level: int = 1,
):
"""Create displacements and supercells.
Distance unit used is that for the calculator interface.
The default unit is Angstron.
The default unit is Angstrom.
"""
optional_structure_info = cell_info["optional_structure_info"]
optional_structure_info = cell_info.optional_structure_info
if settings.displacement_distance is None:
distance = get_default_displacement_distance(interface_mode)
else:
distance = settings.displacement_distance
phono3py = Phono3py(
cell_info["unitcell"],
cell_info["supercell_matrix"],
primitive_matrix=cell_info["primitive_matrix"],
phonon_supercell_matrix=cell_info["phonon_supercell_matrix"],
ph3 = Phono3py(
cell_info.unitcell,
cell_info.supercell_matrix,
primitive_matrix=cell_info.primitive_matrix,
phonon_supercell_matrix=cell_info.phonon_supercell_matrix,
is_symmetry=settings.is_symmetry,
symprec=symprec,
calculator=interface_mode,
)
phono3py.generate_displacements(
distance=distance,
if log_level:
print("")
print('Unit cell was read from "%s".' % optional_structure_info[0])
print("-" * 32 + " unit cell " + "-" * 33) # 32 + 11 + 33 = 76
print_cell(ph3.unitcell)
print("-" * 76)
print_supercell_matrix(ph3.supercell_matrix, ph3.phonon_supercell_matrix)
if ph3.primitive_matrix is not None:
print("Primitive matrix:")
for v in ph3.primitive_matrix:
print(" %s" % v)
print("Displacement distance: %s" % distance)
cutoff_pair_distance = determine_cutoff_pair_distance(
fc_calculator=settings.fc_calculator,
fc_calculator_options=settings.fc_calculator_options,
cutoff_pair_distance=settings.cutoff_pair_distance,
symfc_memory_size=settings.symfc_memory_size,
random_displacements=settings.random_displacements,
supercell=ph3.supercell,
primitive=ph3.primitive,
symmetry=ph3.symmetry,
log_level=log_level,
)
ph3.generate_displacements(
distance=distance,
cutoff_pair_distance=cutoff_pair_distance,
is_plusminus=settings.is_plusminus_displacement,
is_diagonal=settings.is_diagonal_displacement,
number_of_snapshots=settings.random_displacements,
random_seed=settings.random_seed,
number_estimation_factor=settings.rd_number_estimation_factor,
)
if (
settings.random_displacements_fc2
or settings.phonon_supercell_matrix is not None
):
phono3py.generate_fc2_displacements(
ph3.generate_fc2_displacements(
distance=distance,
is_plusminus=settings.is_plusminus_displacement_fc2,
number_of_snapshots=settings.random_displacements_fc2,
random_seed=settings.random_seed,
)
if log_level:
print("")
print('Unit cell was read from "%s".' % optional_structure_info[0])
print("-" * 32 + " unit cell " + "-" * 33) # 32 + 11 + 33 = 76
print_cell(phono3py.unitcell)
print("-" * 76)
print_supercell_matrix(
phono3py.supercell_matrix, phono3py.phonon_supercell_matrix
)
if phono3py.primitive_matrix is not None:
print("Primitive matrix:")
for v in phono3py.primitive_matrix:
print(" %s" % v)
print("Displacement distance: %s" % distance)
ids = []
disp_cells = []
for i, cell in enumerate(phono3py.supercells_with_displacements):
for i, cell in enumerate(ph3.supercells_with_displacements):
if cell is not None:
ids.append(i + 1)
disp_cells.append(cell)
additional_info = get_additional_info_to_write_supercells(
interface_mode, phono3py.supercell_matrix
interface_mode, ph3.supercell_matrix
)
additional_info["supercell_matrix"] = phono3py.supercell_matrix
additional_info["supercell_matrix"] = ph3.supercell_matrix
write_supercells_with_displacements(
interface_mode,
phono3py.supercell,
ph3.supercell,
disp_cells,
optional_structure_info,
displacement_ids=ids,
@ -134,24 +197,25 @@ def create_phono3py_supercells(
)
if log_level:
num_disps = len(phono3py.supercells_with_displacements)
num_disps = len(ph3.supercells_with_displacements)
num_disp_files = len(disp_cells)
print("Number of displacements: %d" % num_disps)
if settings.cutoff_pair_distance is not None:
print(
"Cutoff distance for displacements: %s" % settings.cutoff_pair_distance
)
print("Number of displacement supercell files created: %d" % num_disp_files)
print(f"Number of displacements: {num_disps}")
if cutoff_pair_distance is not None:
print(f"Cutoff distance for displacements: {cutoff_pair_distance}")
print(f"Number of displacement supercell files created: {num_disp_files}")
if phono3py.phonon_supercell_matrix is not None:
num_disps = len(phono3py.phonon_supercells_with_displacements)
if (
ph3.phonon_supercell_matrix is not None
and ph3.phonon_supercells_with_displacements is not None
):
num_disps = len(ph3.phonon_supercells_with_displacements)
additional_info = get_additional_info_to_write_fc2_supercells(
interface_mode, phono3py.phonon_supercell_matrix
interface_mode, ph3.phonon_supercell_matrix
)
write_supercells_with_displacements(
interface_mode,
phono3py.phonon_supercell,
phono3py.phonon_supercells_with_displacements,
ph3.phonon_supercell,
ph3.phonon_supercells_with_displacements,
optional_structure_info,
zfill_width=5,
additional_info=additional_info,
@ -165,11 +229,11 @@ def create_phono3py_supercells(
n_pure_trans = sum(
[
(r == identity).all()
for r in phono3py.symmetry.symmetry_operations["rotations"]
for r in ph3.symmetry.symmetry_operations["rotations"]
]
)
if len(phono3py.supercell) // len(phono3py.primitive) != n_pure_trans:
if len(ph3.supercell) // len(ph3.primitive) != n_pure_trans:
print("*" * 72)
print(
"Note: "
@ -177,4 +241,4 @@ def create_phono3py_supercells(
)
print("*" * 72)
return phono3py
return ph3

View File

@ -224,18 +224,19 @@ def _get_parser():
return args
def _read_files(args: argparse.Namespace) -> tuple[h5py.File, PhonopyAtoms]:
def _read_files(args: argparse.Namespace) -> tuple[h5py.File, PhonopyAtoms | None]:
primitive = None
cell_info = collect_cell_info(
supercell_matrix=np.eye(3, dtype=int),
phonopy_yaml_cls=Phono3pyYaml,
load_phonopy_yaml=True,
)
cell_filename = cell_info["optional_structure_info"][0]
cell_filename = cell_info.optional_structure_info[0]
print(f'# Crystal structure was read from "{cell_filename}".')
cell = cell_info["unitcell"]
phpy_yaml = cell_info.get("phonopy_yaml", None)
cell = cell_info.unitcell
phpy_yaml = cell_info.phonopy_yaml
if phpy_yaml is not None:
primitive = cell_info["phonopy_yaml"].primitive
primitive = phpy_yaml.primitive
if primitive is None:
primitive = cell
f_kappa = h5py.File(args.filenames[0], "r")

View File

@ -38,57 +38,62 @@ from __future__ import annotations
import os
import pathlib
from collections.abc import Sequence
from typing import Optional, Union
from typing import Literal
import numpy as np
import phonopy.cui.load_helper as load_helper
from numpy.typing import NDArray
from phonopy.harmonic.force_constants import show_drift_force_constants
from phonopy.interface.calculator import get_default_physical_units
from phonopy.interface.calculator import get_calculator_physical_units
from phonopy.physical_units import get_physical_units
from phonopy.structure.atoms import PhonopyAtoms
from phonopy.structure.cells import determinant
from phonopy.units import VaspToTHz
from phono3py import Phono3py
from phono3py.cui.create_force_constants import (
develop_or_load_pypolymlp,
parse_forces,
run_pypolymlp_to_compute_forces,
)
from phono3py.file_IO import read_fc2_from_hdf5, read_fc3_from_hdf5
from phono3py.interface.fc_calculator import extract_fc2_fc3_calculators
from phono3py.interface.fc_calculator import (
extract_fc2_fc3_calculators,
extract_fc2_fc3_calculators_options,
update_cutoff_fc_calculator_options,
)
from phono3py.interface.phono3py_yaml import Phono3pyYaml
from phono3py.phonon3.dataset import forces_in_dataset
from phono3py.phonon3.fc3 import show_drift_fc3
def load(
phono3py_yaml: Optional[
Union[str, bytes, os.PathLike]
] = None, # phono3py.yaml-like must be the first argument.
supercell_matrix: Optional[Union[Sequence, np.ndarray]] = None,
primitive_matrix: Optional[Union[Sequence, np.ndarray]] = None,
phonon_supercell_matrix: Optional[Union[Sequence, np.ndarray]] = None,
phono3py_yaml: str
| os.PathLike
| None = None, # phono3py.yaml-like must be the first argument.
supercell_matrix: Sequence | NDArray | None = None,
primitive_matrix: Sequence | NDArray | None = None,
phonon_supercell_matrix: Sequence | NDArray | None = None,
is_nac: bool = True,
calculator: Optional[str] = None,
unitcell: Optional[PhonopyAtoms] = None,
supercell: Optional[PhonopyAtoms] = None,
nac_params: Optional[dict] = None,
unitcell_filename: Optional[Union[str, bytes, os.PathLike]] = None,
supercell_filename: Optional[Union[str, bytes, os.PathLike]] = None,
born_filename: Optional[Union[str, bytes, os.PathLike]] = None,
forces_fc3_filename: Optional[Union[str, bytes, os.PathLike]] = None,
forces_fc2_filename: Optional[Union[str, bytes, os.PathLike]] = None,
fc3_filename: Optional[Union[str, bytes, os.PathLike]] = None,
fc2_filename: Optional[Union[str, bytes, os.PathLike]] = None,
fc_calculator: Optional[str] = None,
fc_calculator_options: Optional[str] = None,
factor: Optional[float] = None,
calculator: str | None = None,
unitcell: PhonopyAtoms | None = None,
supercell: PhonopyAtoms | None = None,
nac_params: dict | None = None,
unitcell_filename: str | os.PathLike | None = None,
supercell_filename: str | os.PathLike | None = None,
born_filename: str | os.PathLike | None = None,
forces_fc3_filename: str | os.PathLike | None = None,
forces_fc2_filename: str | os.PathLike | None = None,
fc3_filename: str | os.PathLike | None = None,
fc2_filename: str | os.PathLike | None = None,
fc_calculator: str | None = None,
fc_calculator_options: str | None = None,
factor: float | None = None,
produce_fc: bool = True,
is_symmetry: bool = True,
symmetrize_fc: bool = True,
is_mesh_symmetry: bool = True,
is_compact_fc: bool = False,
use_pypolymlp: bool = False,
mlp_params: Optional[dict] = None,
mlp_params: dict | None = None,
use_grg: bool = False,
make_r0_average: bool = True,
symprec: float = 1e-5,
@ -112,7 +117,7 @@ def load(
When force_sets_filename and force_constants_filename are not given,
'FORCES_FC3' and 'FORCES_FC2' are looked for in the current directory as the
default behaviour. When 'FORCES_FC3' ('FORCES_FC2') is given in the type-1
default behavior. When 'FORCES_FC3' ('FORCES_FC2') is given in the type-1
format, 'phono3py_disp.yaml' is also necessary and read.
Crystal structure
@ -137,7 +142,7 @@ def load(
also searched in current directory. When 'FORCES_FC2' is not found,
'FORCES_FC3' is used to create fc2.
Parameters for non-analytical term correctiion (NAC)
Parameters for non-analytical term correction (NAC)
----------------------------------------------------
Optional. Means to provide NAC parameters and their priority:
1. born_filename
@ -163,10 +168,10 @@ def load(
given, the centring type ('F', 'I', 'A', 'C', 'R', or primitive 'P') is
automatically chosen. Default is 'auto'.
phonon_supercell_matrix : array_like, optional
Supercell matrix used for fc2. In phono3py, supercell matrix for fc3 and
fc2 can be different to support longer range interaction of fc2 than
Supercell matrix used for fc2. In phono3py, supercell matrix for fc3
and fc2 can be different to support longer range interaction of fc2 than
that of fc3. Unless setting this, supercell_matrix is used. This is only
valide when unitcell or unitcell_filename is given. Default is None.
valid when unitcell or unitcell_filename is given. Default is None.
is_nac : bool, optional
If True, look for 'BORN' file. If False, NAS is turned off. Default is
True.
@ -178,7 +183,7 @@ def load(
Input unit cell. Default is None.
supercell : PhonopyAtoms, optional
Input supercell. With given, default value of primitive_matrix is set to
'auto' (can be overwitten). supercell_matrix is ignored. Default is
'auto' (can be overwritten). supercell_matrix is ignored. Default is
None.
nac_params : dict, optional
Parameters required for non-analytical term correction. Default is None.
@ -186,7 +191,7 @@ def load(
(array_like, shape=(primitive cell atoms, 3, 3), dtype=float),
'dielectric': Dielectric constant matrix
(array_like, shape=(3, 3), dtype=float),
'factor': unit conversion facotr (float)}
'factor': unit conversion factor (float)}
unitcell_filename : os.PathLike, optional
Input unit cell filename. Default is None.
supercell_filename : os.PathLike, optional
@ -214,7 +219,7 @@ def load(
fc_calculator_options : str, optional
Optional parameters that are passed to the external fc-calculator. This
is given as one text string. How to parse this depends on the
fc-calculator. For alm, each parameter is splitted by comma ',', and
fc-calculator. For alm, each parameter is split by comma ',', and
each set of key and value pair is written in 'key = value'.
factor : float, optional
Phonon frequency unit conversion factor. Unless specified, default unit
@ -233,10 +238,10 @@ def load(
True.
is_compact_fc : bool, optional
fc3 are created in the array whose shape is
True: (primitive, supercell, supecell, 3, 3, 3) False: (supercell,
supercell, supecell, 3, 3, 3)
True: (primitive, supercell, supercell, 3, 3, 3) False: (supercell,
supercell, supercell, 3, 3, 3)
and for fc2
True: (primitive, supecell, 3, 3) False: (supercell, supecell, 3, 3)
True: (primitive, supercell, 3, 3) False: (supercell, supercell, 3, 3)
where 'supercell' and 'primitive' indicate number of atoms in these
cells. Default is False.
use_pypolymlp : bool, optional
@ -288,6 +293,7 @@ def load(
elif phono3py_yaml is not None:
ph3py_yaml = Phono3pyYaml()
ph3py_yaml.read(phono3py_yaml)
assert ph3py_yaml.unitcell is not None
cell = ph3py_yaml.unitcell.copy()
_calculator = ph3py_yaml.calculator
smat = ph3py_yaml.supercell_matrix
@ -307,12 +313,12 @@ def load(
_nac_params = None
# Convert distance unit of unit cell to Angstrom
physical_units = get_default_physical_units(_calculator)
physical_units = get_calculator_physical_units(_calculator)
factor_to_A = physical_units["distance_to_A"]
cell.cell = cell.cell * factor_to_A
if factor is None:
_factor = VaspToTHz
_factor = get_physical_units().DefaultToTHz
else:
_factor = factor
ph3py = Phono3py(
@ -343,24 +349,32 @@ def load(
load_fc2_and_fc3(
ph3py, fc3_filename=fc3_filename, fc2_filename=fc2_filename, log_level=log_level
)
load_dataset_and_phonon_dataset(
ph3py.dataset = select_and_load_dataset(
ph3py,
ph3py_yaml,
ph3py_yaml=ph3py_yaml,
forces_fc3_filename=forces_fc3_filename,
forces_fc2_filename=forces_fc2_filename,
phono3py_yaml_filename=phono3py_yaml,
calculator=_calculator,
log_level=log_level,
)
ph3py.phonon_dataset = select_and_load_phonon_dataset(
ph3py,
ph3py_yaml=ph3py_yaml,
forces_fc2_filename=forces_fc2_filename,
calculator=_calculator,
log_level=log_level,
)
if use_pypolymlp and ph3py.fc3 is None and forces_in_dataset(ph3py.dataset):
assert ph3py.dataset is not None
ph3py.mlp_dataset = ph3py.dataset
ph3py.dataset = None
if produce_fc:
if ph3py.fc3 is None and use_pypolymlp:
run_pypolymlp_to_compute_forces(
ph3py, mlp_params=mlp_params, log_level=log_level
)
develop_or_load_pypolymlp(ph3py, mlp_params=mlp_params, log_level=log_level)
compute_force_constants_from_datasets(
ph3py,
@ -368,7 +382,6 @@ def load(
fc_calculator_options=fc_calculator_options,
symmetrize_fc=symmetrize_fc,
is_compact_fc=is_compact_fc,
log_level=log_level,
)
if log_level and ph3py.fc3 is not None:
@ -383,61 +396,28 @@ def load(
def load_fc2_and_fc3(
ph3py: Phono3py,
fc3_filename: Optional[os.PathLike] = None,
fc2_filename: Optional[os.PathLike] = None,
fc3_filename: str | os.PathLike | None = None,
fc2_filename: str | os.PathLike | None = None,
read_fc3: bool = True,
read_fc2: bool = True,
log_level: int = 0,
):
"""Set force constants."""
if fc3_filename is not None or pathlib.Path("fc3.hdf5").exists():
fc3 = _load_fc3(ph3py, fc3_filename=fc3_filename, log_level=log_level)
ph3py.fc3 = fc3
if read_fc3 and (fc3_filename is not None or pathlib.Path("fc3.hdf5").exists()):
_load_fc3(ph3py, fc3_filename=fc3_filename, log_level=log_level)
if fc2_filename is not None or pathlib.Path("fc2.hdf5").exists():
fc2 = _load_fc2(ph3py, fc2_filename=fc2_filename, log_level=log_level)
ph3py.fc2 = fc2
def load_dataset_and_phonon_dataset(
ph3py: Phono3py,
ph3py_yaml: Optional[Phono3pyYaml] = None,
forces_fc3_filename: Optional[Union[os.PathLike, Sequence]] = None,
forces_fc2_filename: Optional[Union[os.PathLike, Sequence]] = None,
phono3py_yaml_filename: Optional[os.PathLike] = None,
cutoff_pair_distance: Optional[float] = None,
calculator: Optional[str] = None,
log_level: int = 0,
):
"""Set displacements, forces, and create force constants."""
dataset = _select_and_load_dataset(
ph3py,
ph3py_yaml=ph3py_yaml,
forces_fc3_filename=forces_fc3_filename,
phono3py_yaml_filename=phono3py_yaml_filename,
cutoff_pair_distance=cutoff_pair_distance,
calculator=calculator,
log_level=log_level,
)
if dataset is not None:
ph3py.dataset = dataset
phonon_dataset = _select_and_load_phonon_dataset(
ph3py,
ph3py_yaml=ph3py_yaml,
forces_fc2_filename=forces_fc2_filename,
calculator=calculator,
log_level=log_level,
)
if phonon_dataset is not None:
ph3py.phonon_dataset = phonon_dataset
if read_fc2 and (fc2_filename is not None or pathlib.Path("fc2.hdf5").exists()):
_load_fc2(ph3py, fc2_filename=fc2_filename, log_level=log_level)
def compute_force_constants_from_datasets(
ph3py: Phono3py,
fc_calculator: Optional[str] = None,
fc_calculator_options: Optional[Union[dict, str]] = None,
fc_calculator: Literal["traditional", "symfc", "alm"] | str | None = None,
fc_calculator_options: str | None = None,
cutoff_pair_distance: float | None = None,
symmetrize_fc: bool = True,
is_compact_fc: bool = True,
log_level: int = 0,
load_phono3py_yaml: bool = False,
):
"""Compute force constants from datasets.
@ -453,19 +433,21 @@ def compute_force_constants_from_datasets(
"""
fc3_calculator = extract_fc2_fc3_calculators(fc_calculator, 3)
fc2_calculator = extract_fc2_fc3_calculators(fc_calculator, 2)
exist_fc2 = ph3py.fc2 is not None
fc3_calc_opts = extract_fc2_fc3_calculators_options(fc_calculator_options, 3)
fc3_calc_opts = update_cutoff_fc_calculator_options(
fc3_calc_opts, cutoff_pair_distance
)
fc2_calc_opts = extract_fc2_fc3_calculators_options(fc_calculator_options, 2)
if ph3py.fc3 is None and forces_in_dataset(ph3py.dataset):
ph3py.produce_fc3(
symmetrize_fc3r=symmetrize_fc,
is_compact_fc=is_compact_fc,
fc_calculator=fc3_calculator,
fc_calculator_options=extract_fc2_fc3_calculators(fc_calculator_options, 3),
fc_calculator_options=fc3_calc_opts,
use_symfc_projector=load_phono3py_yaml,
)
if log_level and symmetrize_fc and fc_calculator is None:
print("fc3 was symmetrized.")
if not exist_fc2:
if ph3py.fc2 is None or fc3_calculator != fc2_calculator:
if (
ph3py.phonon_supercell_matrix is None and forces_in_dataset(ph3py.dataset)
) or (
@ -476,41 +458,49 @@ def compute_force_constants_from_datasets(
symmetrize_fc2=symmetrize_fc,
is_compact_fc=is_compact_fc,
fc_calculator=fc2_calculator,
fc_calculator_options=extract_fc2_fc3_calculators(
fc_calculator_options, 2
),
fc_calculator_options=fc2_calc_opts,
use_symfc_projector=load_phono3py_yaml,
)
if log_level and symmetrize_fc and fc_calculator is None:
print("fc2 was symmetrized.")
def _load_fc3(
ph3py: Phono3py,
fc3_filename: Optional[os.PathLike] = None,
fc3_filename: str | os.PathLike | None = None,
log_level: int = 0,
) -> np.ndarray:
):
p2s_map = ph3py.primitive.p2s_map
if fc3_filename is None:
_fc3_filename = "fc3.hdf5"
else:
_fc3_filename = fc3_filename
fc3 = read_fc3_from_hdf5(filename=_fc3_filename, p2s_map=p2s_map)
_check_fc3_shape(ph3py, fc3, filename=_fc3_filename)
if log_level:
print(f'fc3 was read from "{_fc3_filename}".')
return fc3
if isinstance(fc3, dict):
# fc3 is read from a file with type-1 format.
assert "fc3" in fc3
_check_fc3_shape(ph3py, fc3["fc3"], filename=_fc3_filename)
ph3py.fc3 = fc3["fc3"]
assert "fc3_nonzero_indices" in fc3
ph3py.fc3_nonzero_indices = fc3["fc3_nonzero_indices"]
if log_level:
print(f'fc3 and fc3 nonzero indices were read from "{_fc3_filename}".')
else:
_check_fc3_shape(ph3py, fc3, filename=_fc3_filename)
ph3py.fc3 = fc3
if log_level:
print(f'fc3 was read from "{_fc3_filename}".')
def _select_and_load_dataset(
def select_and_load_dataset(
ph3py: Phono3py,
ph3py_yaml: Optional[Phono3pyYaml] = None,
forces_fc3_filename: Optional[Union[os.PathLike, Sequence]] = None,
phono3py_yaml_filename: Optional[os.PathLike] = None,
cutoff_pair_distance: Optional[float] = None,
calculator: Optional[str] = None,
ph3py_yaml: Phono3pyYaml | None = None,
forces_fc3_filename: str | os.PathLike | Sequence | None = None,
phono3py_yaml_filename: str | os.PathLike | None = None,
cutoff_pair_distance: float | None = None,
calculator: str | None = None,
log_level: int = 0,
) -> Optional[dict]:
dataset = None
) -> dict | None:
"""Select and load dataset for fc3."""
# displacements and forces are in phono3py-yaml-like file
if (
ph3py_yaml is not None
and ph3py_yaml.dataset is not None
@ -525,7 +515,10 @@ def _select_and_load_dataset(
calculator,
log_level,
)
elif forces_fc3_filename is not None or pathlib.Path("FORCES_FC3").exists():
return dataset
# displacements and forces are in FORCES_FC3-like file
if forces_fc3_filename is not None or pathlib.Path("FORCES_FC3").exists():
if forces_fc3_filename is None:
force_filename = "FORCES_FC3"
else:
@ -539,7 +532,10 @@ def _select_and_load_dataset(
calculator,
log_level,
)
elif ph3py_yaml is not None and ph3py_yaml.dataset is not None:
return dataset
# dataset is in phono3py-yaml-like file
if ph3py_yaml is not None and ph3py_yaml.dataset is not None:
# not forces_in_dataset(ph3py_yaml.dataset)
# but want to read displacement dataset.
dataset = _get_dataset_for_fc3(
@ -551,13 +547,14 @@ def _select_and_load_dataset(
calculator,
log_level,
)
return dataset
return dataset
return None
def _load_fc2(
ph3py: Phono3py, fc2_filename: Optional[os.PathLike] = None, log_level: int = 0
) -> np.ndarray:
ph3py: Phono3py, fc2_filename: str | os.PathLike | None = None, log_level: int = 0
):
phonon_p2s_map = ph3py.phonon_primitive.p2s_map
if fc2_filename is None:
_fc2_filename = "fc2.hdf5"
@ -567,22 +564,21 @@ def _load_fc2(
_check_fc2_shape(ph3py, fc2, filename=_fc2_filename)
if log_level:
print(f'fc2 was read from "{_fc2_filename}".')
return fc2
ph3py.fc2 = fc2
def _select_and_load_phonon_dataset(
def select_and_load_phonon_dataset(
ph3py: Phono3py,
ph3py_yaml: Optional[Phono3pyYaml] = None,
forces_fc2_filename: Optional[Union[os.PathLike, Sequence]] = None,
calculator: Optional[str] = None,
ph3py_yaml: Phono3pyYaml | None = None,
forces_fc2_filename: str | os.PathLike | Sequence | None = None,
calculator: str | None = None,
log_level: int = 0,
) -> Optional[dict]:
phonon_dataset = None
if (
ph3py_yaml is not None
and ph3py_yaml.phonon_dataset is not None
and forces_in_dataset(ph3py_yaml.phonon_dataset)
):
) -> dict | None:
"""Select and load phonon dataset for fc2."""
if ph3py.phonon_supercell_matrix is None:
return None
if ph3py_yaml is not None and forces_in_dataset(ph3py_yaml.phonon_dataset):
phonon_dataset = _get_dataset_for_fc2(
ph3py,
ph3py_yaml,
@ -591,9 +587,9 @@ def _select_and_load_phonon_dataset(
calculator,
log_level,
)
elif (
forces_fc2_filename is not None or pathlib.Path("FORCES_FC2").exists()
) and ph3py.phonon_supercell_matrix is not None:
return phonon_dataset
if forces_fc2_filename is not None or pathlib.Path("FORCES_FC2").exists():
if forces_fc2_filename is None:
force_filename = "FORCES_FC2"
else:
@ -606,7 +602,9 @@ def _select_and_load_phonon_dataset(
calculator,
log_level,
)
elif ph3py_yaml is not None and ph3py_yaml.phonon_dataset is not None:
return phonon_dataset
if ph3py_yaml is not None:
# not forces_in_dataset(ph3py_yaml.dataset)
# but want to read displacement dataset.
phonon_dataset = _get_dataset_for_fc2(
@ -617,13 +615,14 @@ def _select_and_load_phonon_dataset(
calculator,
log_level,
)
return phonon_dataset
return phonon_dataset
return None
def _get_dataset_for_fc3(
ph3py: Phono3py,
ph3py_yaml: Optional[Phono3pyYaml],
ph3py_yaml: Phono3pyYaml | None,
force_filename,
phono3py_yaml_filename,
cutoff_pair_distance,
@ -645,7 +644,7 @@ def _get_dataset_for_fc3(
def _get_dataset_for_fc2(
ph3py: Phono3py,
ph3py_yaml: Optional[Phono3pyYaml],
ph3py_yaml: Phono3pyYaml | None,
force_filename,
fc_type,
calculator,
@ -662,7 +661,7 @@ def _get_dataset_for_fc2(
return dataset
def _check_fc2_shape(ph3py: Phono3py, fc2, filename="fc2.hdf5"):
def _check_fc2_shape(ph3py: Phono3py, fc2, filename: str | os.PathLike = "fc2.hdf5"):
if ph3py.phonon_supercell_matrix is None:
smat = ph3py.supercell_matrix
else:
@ -670,7 +669,9 @@ def _check_fc2_shape(ph3py: Phono3py, fc2, filename="fc2.hdf5"):
_check_fc_shape(ph3py, fc2, smat, filename)
def _check_fc3_shape(ph3py: Phono3py, fc3, filename="fc3.hdf5"):
def _check_fc3_shape(
ph3py: Phono3py, fc3: NDArray, filename: str | os.PathLike = "fc3.hdf5"
):
smat = ph3py.supercell_matrix
_check_fc_shape(ph3py, fc3, smat, filename)

View File

@ -34,12 +34,14 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import annotations
import sys
from phonopy.cui.phonopy_argparse import fix_deprecated_option_names
def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
def get_parser(load_phono3py_yaml: bool = False):
"""Return ArgumentParser instance."""
deprecated = fix_deprecated_option_names(sys.argv)
import argparse
@ -56,7 +58,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--alm",
dest="use_alm",
action="store_true",
default=False,
default=None,
help=("Use ALM for generating 2nd and 3rd force constants in one fitting"),
)
parser.add_argument(
@ -70,7 +72,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--ave-pp",
dest="use_ave_pp",
action="store_true",
default=False,
default=None,
help="Use averaged ph-ph interaction",
)
parser.add_argument(
@ -105,7 +107,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
type=float,
default=None,
help=(
"Boundary mean free path in micrometre for thermal conductivity calculation"
"Boundary mean free path in micrometer for thermal conductivity calculation"
),
)
parser.add_argument(
@ -113,7 +115,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--bterta",
dest="is_bterta",
action="store_true",
default=False,
default=None,
help="Calculate thermal conductivity in BTE-RTA",
)
if not load_phono3py_yaml:
@ -155,7 +157,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
metavar="FILE",
dest="subtract_forces",
default=None,
help="Subtract recidual forces from supercell forces",
help="Subtract residual forces from supercell forces",
)
parser.add_argument(
"--cfz-fc2",
@ -163,22 +165,22 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
metavar="FILE",
dest="subtract_forces_fc2",
default=None,
help="Subtract recidual forces from supercell forces for fc2",
help="Subtract residual forces from supercell forces for fc2",
)
parser.add_argument(
"--cfc",
"--compact-fc",
dest="is_compact_fc",
action="store_true",
default=False,
help="Use compact force cosntants",
default=None,
help="Use compact force constants",
)
parser.add_argument(
"--cfs",
"--create-force-sets",
dest="force_sets_mode",
action="store_true",
default=False,
default=None,
help="Create phonopy FORCE_SETS from FORCES_FC2",
)
parser.add_argument(
@ -186,7 +188,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--collective-phonon",
dest="solve_collective_phonon",
action="store_true",
default=False,
default=None,
help="Solve collective phonons",
)
if load_phono3py_yaml:
@ -241,7 +243,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--disp",
dest="is_displacement",
action="store_true",
default=False,
default=None,
help="As first stage, get least displacements",
)
if not load_phono3py_yaml:
@ -263,8 +265,8 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
# "--emulate-v2",
# dest="emulate_v2",
# action="store_true",
# default=False,
# help="Emulate v2.x behaviour.",
# default=None,
# help="Emulate v2.x behavior.",
# )
parser.add_argument(
"--factor",
@ -278,23 +280,16 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--fc2",
dest="read_fc2",
action="store_true",
default=False,
default=None,
help="Read second order force constants",
)
parser.add_argument(
"--fc3",
dest="read_fc3",
action="store_true",
default=False,
default=None,
help="Read third order force constants",
)
parser.add_argument(
"--v2",
dest="is_fc3_r0_average",
action="store_false",
default=True,
help="Take average in fc3-r2q transformation around three atoms",
)
parser.add_argument(
"--fc-calc",
"--fc-calculator",
@ -312,7 +307,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"string with the style of key = values"
),
)
if not fc_symmetry:
if not load_phono3py_yaml:
parser.add_argument(
"--fc-symmetry",
"--sym-fc",
@ -343,7 +338,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--fs2f2",
"--force-sets-to-forces-fc2",
dest="force_sets_to_forces_fc2_mode",
default=False,
default=None,
action="store_true",
help="Create FORCES_FC2 from FORCE_SETS",
)
@ -351,7 +346,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--full-pp",
dest="is_full_pp",
action="store_true",
default=False,
default=None,
help=(
"Calculate full ph-ph interaction for RTA conductivity."
"This may be activated when full elements of ph-ph interaction "
@ -388,14 +383,14 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--generalized-regular-grid",
dest="use_grg",
action="store_true",
default=False,
default=None,
help="Use generalized regular grid.",
)
parser.add_argument(
"--gruneisen",
dest="is_gruneisen",
action="store_true",
default=False,
default=None,
help="Calculate phonon Gruneisen parameter",
)
parser.add_argument(
@ -411,21 +406,11 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
default=None,
help="hdf5 compression filter (default: gzip)",
)
if not load_phono3py_yaml:
parser.add_argument(
"-i", dest="input_filename", default=None, help="Input filename extension"
)
parser.add_argument(
"--io",
dest="input_output_filename",
default=None,
help="Input and output filename extension",
)
parser.add_argument(
"--ion-clamped",
dest="ion_clamped",
action="store_true",
default=False,
default=None,
help=(
"Atoms are clamped under applied strain in Gruneisen parameter calculation"
),
@ -434,35 +419,35 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--ise",
dest="is_imag_self_energy",
action="store_true",
default=False,
default=None,
help="Calculate imaginary part of self energy",
)
parser.add_argument(
"--isotope",
dest="is_isotope",
action="store_true",
default=False,
default=None,
help="Isotope scattering lifetime",
)
parser.add_argument(
"--jdos",
dest="is_joint_dos",
action="store_true",
default=False,
default=None,
help="Calculate joint density of states",
)
parser.add_argument(
"--kubo",
dest="is_kubo_kappa",
action="store_true",
default=False,
default=None,
help="Choose Kubo lattice thermal conductivity.",
)
parser.add_argument(
"--lbte",
dest="is_lbte",
action="store_true",
default=False,
default=None,
help="Calculate thermal conductivity LBTE with Chaput's method",
)
parser.add_argument(
@ -494,7 +479,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
default=None,
help="Mass variance parameters for isotope scattering",
)
if not is_nac:
if not load_phono3py_yaml:
parser.add_argument(
"--nac",
dest="is_nac",
@ -508,7 +493,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
default=None,
help="Non-analytical term correction method: Gonze (default) or Wang",
)
if fc_symmetry:
if load_phono3py_yaml:
parser.add_argument(
"--no-fc-symmetry",
"--no-sym-fc",
@ -517,29 +502,44 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
default=None,
help="Do not symmetrize force constants",
)
parser.add_argument(
"--no-read-fc2",
dest="read_fc2",
action="store_false",
default=None,
help="Read second order force constants",
)
parser.add_argument(
"--no-read-fc3",
dest="read_fc3",
action="store_false",
default=None,
help="Read third order force constants",
)
parser.add_argument(
"--nodiag",
dest="is_nodiag",
action="store_true",
default=False,
default=None,
help="Set displacements parallel to axes",
)
parser.add_argument(
"--noks",
"--no-kappa-stars",
dest="no_kappa_stars",
action="store_true",
default=False,
dest="kappa_star",
action="store_false",
default=None,
help="Deactivate summation of partial kappa at q-stars",
)
parser.add_argument(
"--nomeshsym",
dest="is_nomeshsym",
action="store_true",
default=False,
default=None,
help="No symmetrization of triplets is made.",
)
if is_nac:
if load_phono3py_yaml:
parser.add_argument(
"--nonac",
dest="is_nac",
@ -551,14 +551,14 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--nosym",
dest="is_nosym",
action="store_true",
default=False,
default=None,
help="Symmetry is not imposed.",
)
parser.add_argument(
"--nu",
dest="is_N_U",
action="store_true",
default=False,
default=None,
help="Split Gamma into Normal and Umklapp processes",
)
parser.add_argument(
@ -585,10 +585,6 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
default=None,
help="Output yaml filename instead of default filename of phono3py.yaml",
)
else:
parser.add_argument(
"-o", dest="output_filename", default=None, help="Output filename extension"
)
parser.add_argument(
"--pa",
"--primitive-axis",
@ -623,14 +619,14 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--pm",
dest="is_plusminus_displacements",
action="store_true",
default=False,
default=None,
help="Set plus minus displacements",
)
parser.add_argument(
"--pm-fc2",
dest="is_plusminus_displacements_fc2",
action="store_true",
default=False,
default=None,
help="Set plus minus displacements for extra fc2",
)
parser.add_argument(
@ -644,7 +640,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--pypolymlp",
dest="use_pypolymlp",
action="store_true",
default=False,
default=None,
help="Use pypolymlp and symfc for generating force constants",
)
parser.add_argument(
@ -666,7 +662,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--quiet",
dest="quiet",
action="store_true",
default=False,
default=None,
help="Print out smallest information",
)
parser.add_argument(
@ -683,6 +679,13 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
default=None,
help='Number of supercells with random displacements or "auto"',
)
parser.add_argument(
"--rd-auto-factor",
dest="rd_number_estimation_factor",
type=float,
default=None,
help="Factor to estimate number of supercells with random displacements",
)
parser.add_argument(
"--rd-fc2",
"--random-displacements-fc2",
@ -700,35 +703,42 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--read-gamma",
dest="read_gamma",
action="store_true",
default=False,
default=None,
help="Read Gammas from files",
)
parser.add_argument(
"--read-phonon",
dest="read_phonon",
action="store_true",
default=False,
default=None,
help="Read phonons from files",
)
parser.add_argument(
"--read-pp",
dest="read_pp",
action="store_true",
default=False,
default=None,
help="Read phonon-phonon interaction strength",
)
parser.add_argument(
"--reducible-colmat",
dest="is_reducible_collision_matrix",
action="store_true",
default=False,
default=None,
help="Solve reducible collision matrix",
)
parser.add_argument(
"--relax-atomic-positions",
dest="relax_atomic_positions",
action="store_true",
default=None,
help="Relax atomic positions using polynomial MLPs",
)
parser.add_argument(
"--rse",
dest="is_real_self_energy",
action="store_true",
default=False,
default=None,
help="Calculate real part of self energy",
)
parser.add_argument(
@ -770,11 +780,26 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
default=None,
help="Use symfc for generating force constants",
)
if load_phono3py_yaml:
parser.add_argument(
"--symfc-memshow",
dest="show_symfc_memory_usage",
action="store_true",
default=None,
help="Show symfc memory usage with respect to cutoff distance",
)
parser.add_argument(
"--symfc-memsize",
dest="symfc_memory_size",
type=float,
default=None,
help="Memory size to estimate cutoff pair distance (GB)",
)
parser.add_argument(
"--spf",
dest="is_spectral_function",
action="store_true",
default=False,
default=None,
help="Calculate spectral function",
)
parser.add_argument(
@ -782,7 +807,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--show-num-triplets",
dest="show_num_triplets",
action="store_true",
default=False,
default=None,
help=(
"Show reduced number of triplets to be calculated at specified grid points"
),
@ -792,21 +817,21 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--sym-fc2",
dest="is_symmetrize_fc2",
action="store_true",
default=False,
default=None,
help="Symmetrize fc2 by index exchange",
)
parser.add_argument(
"--sym-fc3r",
dest="is_symmetrize_fc3_r",
action="store_true",
default=False,
default=None,
help="Symmetrize fc3 in real space by index exchange",
)
parser.add_argument(
"--sym-fc3q",
dest="is_symmetrize_fc3_q",
action="store_true",
default=False,
default=None,
help="Symmetrize fc3 in reciprocal space by index exchange",
)
parser.add_argument(
@ -814,7 +839,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--tetrahedron-method",
dest="is_tetrahedron_method",
action="store_true",
default=False,
default=None,
help="Use tetrahedron method.",
)
parser.add_argument(
@ -851,15 +876,22 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--verbose",
dest="verbose",
action="store_true",
default=False,
default=None,
help="Detailed run-time information is displayed",
)
parser.add_argument(
"--v2",
dest="is_fc3_r0_average",
action="store_false",
default=None,
help="Take average in fc3-r2q transformation around three atoms",
)
parser.add_argument(
"--wgp",
"--write-grid-points",
dest="write_grid_points",
action="store_true",
default=False,
default=None,
help=(
"Write grid address of irreducible grid points for specified "
"mesh numbers to ir_grid_address.yaml"
@ -869,21 +901,21 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--wigner",
dest="is_wigner_kappa",
action="store_true",
default=False,
default=None,
help="Choose Wigner lattice thermal conductivity.",
)
parser.add_argument(
"--write-collision",
dest="write_collision",
action="store_true",
default=False,
default=None,
help="Write collision matrix and Gammas to files",
)
parser.add_argument(
"--write-gamma",
dest="write_gamma",
action="store_true",
default=False,
default=None,
help="Write imag-part of self energy to files",
)
parser.add_argument(
@ -891,28 +923,28 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--write_detailed_gamma",
dest="write_gamma_detail",
action="store_true",
default=False,
default=None,
help="Write out detailed imag-part of self energy",
)
parser.add_argument(
"--write-phonon",
dest="write_phonon",
action="store_true",
default=False,
default=None,
help="Write all phonons on grid points to files",
)
parser.add_argument(
"--write-pp",
dest="write_pp",
action="store_true",
default=False,
default=None,
help="Write phonon-phonon interaction strength",
)
parser.add_argument(
"--write-lbte-solution",
dest="write_LBTE_solution",
action="store_true",
default=False,
default=None,
help="Write direct solution of LBTE to hdf5 files",
)
if load_phono3py_yaml:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -34,9 +34,10 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import annotations
import sys
from collections.abc import Sequence
from typing import Optional, Union
import numpy as np
from phonopy.structure.cells import print_cell
@ -46,13 +47,11 @@ from phono3py.cui.settings import Phono3pySettings
def show_general_settings(
settings,
run_mode,
phono3py,
cell_filename,
input_filename,
output_filename,
interface_mode,
settings: Phono3pySettings,
run_mode: str,
phono3py: Phono3py,
cell_filename: str,
interface_mode: str | None,
):
"""Show general setting information."""
is_primitive_axes_auto = (
@ -64,12 +63,13 @@ def show_general_settings(
phonon_supercell_matrix = phono3py.phonon_supercell_matrix
print("-" * 29 + " General settings " + "-" * 29)
if run_mode:
if settings.use_pypolymlp:
if settings.create_displacements or settings.random_displacements is not None:
print(f"Run mode: pypolymlp + {run_mode}")
else:
print("Run mode: pypolymlp")
else:
print(f"Run mode: {run_mode}")
if output_filename:
print(f"Output filename is modified by {output_filename}.")
if input_filename:
print(f"Input filename is modified by {input_filename}.")
if settings.hdf5_compression:
print(f"HDF5 data compression filter: {settings.hdf5_compression}")
if interface_mode:
@ -82,19 +82,18 @@ def show_general_settings(
print_supercell_matrix(supercell_matrix, phonon_supercell_matrix)
if is_primitive_axes_auto:
print("Primitive matrix (Auto):")
for v in primitive_matrix:
print(f" {v}")
elif primitive_matrix is not None:
print("Primitive matrix:")
if primitive_matrix is not None:
if is_primitive_axes_auto:
print("Primitive matrix (Auto):")
else:
print("Primitive matrix:")
for v in primitive_matrix:
print(f" {v}")
def print_supercell_matrix(
supercell_matrix: Union[Sequence, np.ndarray],
phonon_supercell_matrix: Optional[Union[Sequence, np.ndarray]] = None,
supercell_matrix: Sequence | np.ndarray,
phonon_supercell_matrix: Sequence | np.ndarray | None = None,
):
"""Print supercell matrix."""
if (np.diag(np.diag(supercell_matrix)) - supercell_matrix).any():

View File

@ -34,10 +34,12 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from collections.abc import Sequence
from typing import Optional, Union
from __future__ import annotations
import os
import numpy as np
from numpy.typing import ArrayLike
from phonopy.structure.atoms import PhonopyAtoms
from phono3py.file_IO import write_grid_address_to_hdf5, write_ir_grid_points
@ -48,13 +50,13 @@ from phono3py.phonon3.triplets import get_triplets_at_q
def write_grid_points(
primitive: PhonopyAtoms,
bz_grid: BZGrid,
band_indices: Optional[Union[Sequence, np.ndarray]] = None,
sigmas: Optional[Union[Sequence, np.ndarray]] = None,
temperatures: Optional[Union[Sequence, np.ndarray]] = None,
band_indices: ArrayLike | None = None,
sigmas: ArrayLike | None = None,
temperatures: ArrayLike | None = None,
is_kappa_star: bool = True,
is_lbte: bool = False,
compression: Union[str, int] = "gzip",
filename: bool = None,
compression: str | int = "gzip",
filename: str | os.PathLike | None = None,
):
"""Write grid points into files."""
ir_grid_points, ir_grid_weights = _get_ir_grid_points(
@ -109,8 +111,8 @@ def write_grid_points(
def show_num_triplets(
primitive: PhonopyAtoms,
bz_grid: BZGrid,
band_indices: Optional[Union[Sequence, np.ndarray]] = None,
grid_points: Optional[Union[Sequence, np.ndarray]] = None,
band_indices: ArrayLike | None = None,
grid_points: ArrayLike | None = None,
is_kappa_star: bool = True,
):
"""Show numbers of triplets at grid points."""

View File

@ -36,12 +36,14 @@
from __future__ import annotations
import os
import pathlib
import warnings
from collections.abc import Sequence
from typing import Optional, TextIO, Union
import h5py
import numpy as np
from numpy.typing import NDArray
from phonopy.cui.load_helper import read_force_constants_from_hdf5
# This import is deactivated for a while.
@ -52,6 +54,7 @@ from phonopy.file_IO import (
write_FORCE_SETS,
)
from phono3py.phonon.grid import BZGrid
from phono3py.version import __version__
@ -300,34 +303,54 @@ def _write_FORCES_FC3_typeI(
count += 1
def write_fc3_to_hdf5(fc3, filename="fc3.hdf5", p2s_map=None, compression="gzip"):
def write_fc3_to_hdf5(
fc3: NDArray,
fc3_nonzero_indices: NDArray | None = None,
filename: str = "fc3.hdf5",
p2s_map: NDArray | None = None,
fc3_cutoff: float | None = None,
compression: str = "gzip",
):
"""Write fc3 in fc3.hdf5.
Parameters
----------
force_constants : ndarray
Force constants
shape=(n_satom, n_satom, n_satom, 3, 3, 3) or
(n_patom, n_satom, n_satom,3,3,3), dtype=double
fc3 : ndarray
Force constants shape=(n_satom, n_satom, n_satom, 3, 3, 3) or (n_patom,
n_satom, n_satom,3,3,3), dtype=double
fc3_nonzero_indices : ndarray, optional
Non-zero indices of fc3. shape=(n_satom, n_satom, n_satom) or (n_patom,
n_satom, n_satom), dtype="byte". If this is given, fc3 is in compact
format. Otherwise, it is in full format.
filename : str
Filename to be used.
p2s_map : ndarray, optional
Primitive atom indices in supercell index system
shape=(n_patom,), dtype=intc
Primitive atom indices in supercell index system shape=(n_patom,),
dtype=intc
fc3_cutoff : float, optional
Cutoff distance for fc3.
compression : str or int, optional
h5py's lossless compression filters (e.g., "gzip", "lzf"). None gives
no compression. See the detail at docstring of
h5py.Group.create_dataset. Default is "gzip".
h5py's lossless compression filters (e.g., "gzip", "lzf"). None gives no
compression. See the detail at docstring of h5py.Group.create_dataset.
Default is "gzip".
"""
with h5py.File(filename, "w") as w:
w.create_dataset("version", data=np.bytes_(__version__))
w.create_dataset("fc3", data=fc3, compression=compression)
if fc3_nonzero_indices is not None:
w.create_dataset(
"fc3_nonzero_indices", data=fc3_nonzero_indices, compression=compression
)
if fc3_cutoff is not None:
w.create_dataset("fc3_cutoff", data=fc3_cutoff)
if p2s_map is not None:
w.create_dataset("p2s_map", data=p2s_map)
def read_fc3_from_hdf5(filename="fc3.hdf5", p2s_map=None):
def read_fc3_from_hdf5(
filename: str | os.PathLike = "fc3.hdf5", p2s_map: NDArray | None = None
) -> NDArray | dict:
"""Read fc3 from fc3.hdf5.
fc3 can be in full or compact format. They are distinguished by
@ -339,20 +362,44 @@ def read_fc3_from_hdf5(filename="fc3.hdf5", p2s_map=None):
"""
with h5py.File(filename, "r") as f:
fc3 = f["fc3"][:]
if "fc3" not in f:
raise KeyError(
f"{filename} does not have 'fc3' dataset. "
"This file is not a valid fc3.hdf5."
)
fc3: NDArray = f["fc3"][:] # type: ignore
if fc3.dtype == np.dtype("double") and fc3.flags.c_contiguous:
pass
else:
raise TypeError(
f"{filename} has to be read by h5py as numpy ndarray of "
"dtype='double' and c_contiguous."
)
if "p2s_map" in f:
p2s_map_in_file = f["p2s_map"][:]
check_force_constants_indices(
fc3.shape[:2], p2s_map_in_file, p2s_map, filename
)
if fc3.dtype == np.dtype("double") and fc3.flags.c_contiguous:
fc3_nonzero_indices = None # type: ignore
if "fc3_nonzero_indices" in f:
fc3_nonzero_indices: NDArray = f["fc3_nonzero_indices"][:] # type: ignore
if (
fc3_nonzero_indices.dtype == np.dtype("byte")
and fc3_nonzero_indices.flags.c_contiguous
):
pass
else:
raise TypeError(
f"{filename} has to be read by h5py as numpy ndarray of "
"dtype='byte' and c_contiguous."
)
if fc3_nonzero_indices is None:
return fc3
else:
msg = (
"%s has to be read by h5py as numpy ndarray of "
"dtype='double' and c_contiguous." % filename
)
raise TypeError(msg)
return {"fc3": fc3, "fc3_nonzero_indices": fc3_nonzero_indices}
def write_fc2_to_hdf5(
@ -406,7 +453,7 @@ def write_fc2_to_hdf5(
)
def read_fc2_from_hdf5(filename="fc2.hdf5", p2s_map=None):
def read_fc2_from_hdf5(filename: str | os.PathLike = "fc2.hdf5", p2s_map=None):
"""Read fc2 from fc2.hdf5."""
return read_force_constants_from_hdf5(
filename=filename, p2s_map=p2s_map, calculator="vasp"
@ -415,7 +462,7 @@ def read_fc2_from_hdf5(filename="fc2.hdf5", p2s_map=None):
def write_datasets_to_hdf5(
dataset: dict,
phonon_dataset: dict = None,
phonon_dataset: dict | None = None,
filename: str = "datasets.hdf5",
compression: str = "gzip",
):
@ -437,9 +484,9 @@ def write_grid_address_to_hdf5(
grid_address,
mesh,
grid_mapping_table,
bz_grid=None,
compression: Union[str, int] = "gzip",
filename=None,
bz_grid: BZGrid | None = None,
compression: str | int = "gzip",
filename: str | os.PathLike | None = None,
):
"""Write grid addresses to grid_address.hdf5."""
suffix = _get_filename_suffix(mesh, filename=filename)
@ -613,7 +660,7 @@ def write_real_self_energy_to_hdf5(
frequencies=None,
filename=None,
):
"""Wirte real part of self energy (currently only bubble) in hdf5.
"""Write real part of self energy (currently only bubble) in hdf5.
deltas : ndarray
Real part of self energy.
@ -702,7 +749,7 @@ def write_spectral_function_to_hdf5(
all_band_exist=False,
filename=None,
):
"""Wirte spectral functions (currently only bubble) in hdf5.
"""Write spectral functions (currently only bubble) in hdf5.
spectral_functions : ndarray
Spectral functions.
@ -792,7 +839,7 @@ def write_collision_to_hdf5(
text = "Collisions "
if grid_point is not None:
text += "at grid adress %d " % grid_point
text += "at grid address %d " % grid_point
if sigma is not None:
if grid_point is not None:
text += "and "
@ -827,7 +874,7 @@ def write_unitary_matrix_to_hdf5(
):
"""Write eigenvectors of collision matrices at temperatures.
Depending on the choice of the solver, eigenvectors are sotred in
Depending on the choice of the solver, eigenvectors are stored in
either column-wise or row-wise.
"""
@ -1090,7 +1137,7 @@ def read_gamma_from_hdf5(
filename=filename,
)
full_filename = "kappa" + suffix + ".hdf5"
if not os.path.exists(full_filename):
if not pathlib.Path(full_filename).exists():
return None, full_filename
read_data = {}
@ -1109,7 +1156,7 @@ def read_gamma_from_hdf5(
def read_collision_from_hdf5(
mesh,
indices=None,
indices: str | Sequence = "all",
grid_point=None,
band_index=None,
sigma=None,
@ -1117,8 +1164,8 @@ def read_collision_from_hdf5(
filename=None,
only_temperatures=False,
verbose=True,
):
"""Read colliction matrix.
) -> tuple:
"""Read collision matrix.
indices : array_like of int
Indices of temperatures.
@ -1137,10 +1184,8 @@ def read_collision_from_hdf5(
filename=filename,
)
full_filename = "collision" + suffix + ".hdf5"
if not os.path.exists(full_filename):
if verbose:
print("%s not found." % full_filename)
return None
if not pathlib.Path(full_filename).exists():
raise FileNotFoundError(f"{full_filename} not found.")
if only_temperatures:
with h5py.File(full_filename, "r") as f:
@ -1290,7 +1335,7 @@ def read_pp_from_hdf5(
filename=None,
verbose=True,
check_consistency=False,
):
) -> tuple:
"""Read ph-ph interaction strength from its hdf5 file."""
suffix = _get_filename_suffix(
mesh,
@ -1300,10 +1345,8 @@ def read_pp_from_hdf5(
filename=filename,
)
full_filename = "pp" + suffix + ".hdf5"
if not os.path.exists(full_filename):
if verbose:
print("%s not found." % full_filename)
return None
if not pathlib.Path(full_filename).exists():
raise FileNotFoundError(f"{full_filename} not found.")
with h5py.File(full_filename, "r") as f:
if "nonzero_pp" in f:
@ -1346,7 +1389,7 @@ def read_pp_from_hdf5(
return pp, g_zero
return None
raise RuntimeError(f"pp data not found in {full_filename}.")
def write_gamma_detail_to_hdf5(
@ -1479,14 +1522,12 @@ def write_phonon_to_hdf5(
return None
def read_phonon_from_hdf5(mesh, filename=None, verbose=True):
def read_phonon_from_hdf5(mesh, filename=None, verbose=True) -> tuple:
"""Read phonon from its hdf5 file."""
suffix = _get_filename_suffix(mesh, filename=filename)
full_filename = "phonon" + suffix + ".hdf5"
if not os.path.exists(full_filename):
if verbose:
print("%s not found." % full_filename)
return None
if not pathlib.Path(full_filename).exists():
raise FileNotFoundError(f"{full_filename} not found.")
with h5py.File(full_filename, "r") as f:
frequencies = np.array(f["frequency"][:], dtype="double", order="C")
@ -1504,8 +1545,6 @@ def read_phonon_from_hdf5(mesh, filename=None, verbose=True):
return frequencies, eigenvectors, grid_address
return None
def write_ir_grid_points(bz_grid, grid_points, grid_weights, primitive_lattice):
"""Write ir-grid-points in yaml."""
@ -1605,7 +1644,11 @@ def parse_disp_fc3_yaml(filename="disp_fc3.yaml", return_cell=False):
return new_dataset
def parse_FORCES_FC2(disp_dataset, filename="FORCES_FC2", unit_conversion_factor=None):
def parse_FORCES_FC2(
disp_dataset: dict,
filename: str | os.PathLike = "FORCES_FC2",
unit_conversion_factor: float | None = None,
):
"""Parse type1 FORCES_FC2 file and store forces in disp_dataset."""
num_atom = disp_dataset["natom"]
num_disp = len(disp_dataset["first_atoms"])
@ -1626,7 +1669,10 @@ def parse_FORCES_FC2(disp_dataset, filename="FORCES_FC2", unit_conversion_factor
def parse_FORCES_FC3(
disp_dataset, filename="FORCES_FC3", use_loadtxt=False, unit_conversion_factor=None
disp_dataset: dict,
filename: str | os.PathLike = "FORCES_FC3",
use_loadtxt: bool = False,
unit_conversion_factor: float | None = None,
):
"""Parse type1 FORCES_FC3 and store forces in disp_dataset."""
num_atom = disp_dataset["natom"]
@ -1697,7 +1743,7 @@ def get_length_of_first_line(f):
f.seek(0)
return len(line.split())
raise RuntimeError("File doesn't contain relevant infomration.")
raise RuntimeError("File doesn't contain relevant information.")
def _get_filename_suffix(

View File

@ -36,90 +36,95 @@
from __future__ import annotations
from typing import Optional, Union
from typing import Literal
import numpy as np
from phonopy.interface.fc_calculator import FCSolver, fc_calculator_names
from phonopy.interface.symfc import parse_symfc_options, update_symfc_cutoff_by_memsize
from phonopy.structure.atoms import PhonopyAtoms
from phonopy.structure.cells import Primitive
from phonopy.structure.symmetry import Symmetry
from phono3py.phonon3.dataset import get_displacements_and_forces_fc3
from phono3py.phonon3.fc3 import get_fc3
def get_fc3(
supercell: PhonopyAtoms,
primitive: Primitive,
displacements: np.ndarray,
forces: np.ndarray,
fc_calculator: Optional[str] = None,
fc_calculator_options: Optional[str] = None,
is_compact_fc: bool = False,
symmetry: Optional[Symmetry] = None,
log_level: int = 0,
):
"""Calculate 2upercell 2nd and 3rd order force constants.
Parameters
----------
supercell : PhonopyAtoms
Supercell
primitive : Primitive
Primitive cell
displacements : array_like
Displacements of atoms in supercell.
shape=(num_snapshots, num_atoms, 3), dtype='double', order='C'
forces : array_like
Forces of atoms in supercell.
shape=(num_snapshots, num_atoms, 3), dtype='double', order='C'
fc_calculator : str, optional
Currently only 'alm' is supported. Default is None, meaning invoking
'alm'.
fc_calculator_options : str, optional
This is arbitrary string.
log_level : integer or bool, optional
Verbosity level. False or 0 means quiet. True or 1 means normal level
of log to stdout. 2 gives verbose mode.
class FDFC3Solver:
"""Finite difference type force constants calculator.
Returns
-------
(fc2, fc3) : tuple[ndarray]
2nd and 3rd order force constants.
This is phono3py's traditional force constants calculator.
"""
if fc_calculator == "alm":
from phonopy.interface.alm import run_alm
fc = run_alm(
def __init__(
self,
supercell: PhonopyAtoms,
primitive: Primitive,
symmetry: Symmetry,
dataset: dict,
is_compact_fc: bool = False,
log_level: int = 0, # currently not used
):
self._fc2, self._fc3 = self._run(
supercell,
primitive,
displacements,
forces,
2,
options=fc_calculator_options,
is_compact_fc=is_compact_fc,
log_level=log_level,
symmetry,
dataset,
is_compact_fc,
log_level,
)
return fc[2], fc[3]
elif fc_calculator == "symfc":
from phonopy.interface.symfc import run_symfc
fc = run_symfc(
@property
def force_constants(self) -> dict[int, np.ndarray]:
"""Return force constants.
Returns
-------
dict[int, np.ndarray]
Force constants with order as key.
"""
return {2: self._fc2, 3: self._fc3}
def _run(
self,
supercell: PhonopyAtoms,
primitive: Primitive,
symmetry: Symmetry,
dataset: dict,
is_compact_fc: bool,
log_level: int,
):
return get_fc3(
supercell,
primitive,
displacements,
forces,
orders=[2, 3],
dataset,
symmetry,
is_compact_fc=is_compact_fc,
symmetry=symmetry,
options=fc_calculator_options,
log_level=log_level,
verbose=log_level > 0,
)
return fc[2], fc[3]
else:
msg = "Force constants calculator of %s was not found ." % fc_calculator
raise RuntimeError(msg)
def extract_fc2_fc3_calculators(fc_calculator: Optional[Union[str, dict]], order: int):
"""Extract fc_calculator and fc_calculator_options for fc2 and fc3.
class FC3Solver(FCSolver):
"""Force constants solver for fc3."""
def _set_traditional_solver(self, solver_class: type | None = FDFC3Solver):
return super()._set_traditional_solver(solver_class=solver_class)
def _set_symfc_solver(self):
return super()._set_symfc_solver(order=3)
def _get_displacements_and_forces(self):
"""Return displacements and forces for fc3."""
assert self._dataset is not None
return get_displacements_and_forces_fc3(self._dataset)
def extract_fc2_fc3_calculators(
fc_calculator: Literal["traditional", "symfc", "alm"] | str | None,
order: int,
) -> Literal["traditional", "symfc", "alm"] | None:
"""Extract fc_calculator for fc2 and fc3.
fc_calculator : str
FC calculator. "|" separates fc2 and fc3. First and last
@ -128,17 +133,204 @@ def extract_fc2_fc3_calculators(fc_calculator: Optional[Union[str, dict]], order
2 and 3 indicate fc2 and fc3, respectively.
"""
if isinstance(fc_calculator, dict) or fc_calculator is None:
return fc_calculator
elif isinstance(fc_calculator, str):
if "|" in fc_calculator:
_fc_calculator = fc_calculator.split("|")[order - 2]
if _fc_calculator == "":
return None
return _fc_calculator
else:
if fc_calculator.strip() == "":
return None
return fc_calculator
if fc_calculator is None:
return None
else:
raise RuntimeError("fc_calculator should be str or dict.")
_fc_calculator = _split_fc_calculator_str(fc_calculator, order)
if _fc_calculator is None:
return None
fc_calculator_lower = _fc_calculator.lower()
if fc_calculator_lower not in ("traditional", "symfc", "alm"):
raise ValueError(
f"Unknown fc_calculator: {_fc_calculator}. "
"Available calculators are 'traditional', 'symfc', and 'alm'."
)
return fc_calculator_lower
def extract_fc2_fc3_calculators_options(
fc_calculator_opts: str | None,
order: int,
) -> str | None:
"""Extract fc_calculator_options for fc2 and fc3.
fc_calculator_opts : str
FC calculator options. "|" separates fc2 and fc3. First and last
parts separated correspond to fc2 and fc3 calculators, respectively.
order : int = 2 or 3
2 and 3 indicate fc2 and fc3, respectively.
"""
if fc_calculator_opts is None:
return None
else:
_fc_calculator_opts = _split_fc_calculator_str(fc_calculator_opts, order)
return _fc_calculator_opts
def _split_fc_calculator_str(fc_calculator: str, order: int) -> str | None:
if "|" in fc_calculator:
_fc_calculator = fc_calculator.split("|")[order - 2]
if _fc_calculator == "":
return None
else:
if fc_calculator.strip() == "":
return None
else:
_fc_calculator = fc_calculator
return _fc_calculator
def update_cutoff_fc_calculator_options(
fc_calc_opts: str | None,
cutoff_pair_distance: float | None,
) -> str | None:
"""Update fc_calculator_options with cutoff distances.
Parameters
----------
fc_calc_opts : str or None
FC calculator options.
cutoff_pair_distance : float, optional
Cutoff distance for pair interaction.
"""
if cutoff_pair_distance is not None:
if isinstance(fc_calc_opts, str) and "cutoff" not in fc_calc_opts:
fc_calc_opts = f"{fc_calc_opts}, cutoff = {cutoff_pair_distance}"
elif fc_calc_opts is None:
fc_calc_opts = f"cutoff = {cutoff_pair_distance}"
return fc_calc_opts
def get_fc_calculator_params(
fc_calculator: str | None,
fc_calculator_options: str | None,
cutoff_pair_distance: float | None,
log_level: int = 0,
) -> tuple[str | None, str | None]:
"""Compile fc_calculator and fc_calculator_options from input settings."""
_fc_calculator = None
fc_calculator_list = []
if fc_calculator is not None:
for fc_calculatr_str in fc_calculator.split("|"):
if fc_calculatr_str == "": # No external calculator
fc_calculator_list.append(fc_calculatr_str.lower())
elif fc_calculatr_str.lower() in fc_calculator_names:
fc_calculator_list.append(fc_calculatr_str.lower())
if fc_calculator_list:
_fc_calculator = "|".join(fc_calculator_list)
_fc_calculator_options = fc_calculator_options
if cutoff_pair_distance:
if fc_calculator_list and fc_calculator_list[-1] in ("alm", "symfc"):
if fc_calculator_list[-1] == "alm":
cutoff_str = f"-1 {cutoff_pair_distance}"
if fc_calculator_list[-1] == "symfc":
cutoff_str = f"{cutoff_pair_distance}"
_fc_calculator_options = _set_cutoff_in_fc_calculator_options(
_fc_calculator_options,
cutoff_str,
log_level,
)
return _fc_calculator, _fc_calculator_options
def determine_cutoff_pair_distance(
fc_calculator: str | None = None,
fc_calculator_options: str | None = None,
cutoff_pair_distance: float | None = None,
symfc_memory_size: float | None = None,
random_displacements: int | str | None = None,
supercell: PhonopyAtoms | None = None,
primitive: Primitive | None = None,
symmetry: Symmetry | None = None,
log_level: int = 0,
) -> float | None:
"""Determine cutoff pair distance for displacements."""
_cutoff_pair_distance, _symfc_memory_size = _get_cutoff_pair_distance(
fc_calculator,
fc_calculator_options,
cutoff_pair_distance,
symfc_memory_size,
)
if random_displacements is not None and random_displacements != "auto":
_symfc_memory_size = None
if _symfc_memory_size is not None:
if fc_calculator is None:
pass
elif fc_calculator != "symfc":
raise RuntimeError(
"Estimation of cutoff_pair_distance by memory size is only "
"available for symfc calculator."
)
symfc_options = {"memsize": {3: _symfc_memory_size}}
if supercell is None or primitive is None or symmetry is None:
raise RuntimeError(
"supercell, primitive, and symmetry are required to estimate "
"cutoff_pair_distance by memory size."
)
update_symfc_cutoff_by_memsize(
symfc_options, supercell, primitive, symmetry, verbose=log_level > 0
)
if symfc_options["cutoff"] is not None:
_cutoff_pair_distance = symfc_options["cutoff"][3]
return _cutoff_pair_distance
def _set_cutoff_in_fc_calculator_options(
fc_calculator_options: str | None,
cutoff_str: str,
log_level: int,
):
str_appended = f"cutoff={cutoff_str}"
calc_opts = fc_calculator_options
if calc_opts is None:
calc_opts = "|"
if "|" in calc_opts:
calc_opts_fc2, calc_opts_fc3 = [v.strip() for v in calc_opts.split("|")][:2]
else:
calc_opts_fc2 = calc_opts
calc_opts_fc3 = calc_opts
if calc_opts_fc3 == "":
calc_opts_fc3 += f"{str_appended}"
if log_level:
print(f'Set "{str_appended}" to fc_calculator_options for fc3.')
elif "cutoff" not in calc_opts_fc3:
calc_opts_fc3 += f", {str_appended}"
if log_level:
print(f'Appended "{str_appended}" to fc_calculator_options for fc3.')
return f"{calc_opts_fc2}|{calc_opts_fc3}"
def _get_cutoff_pair_distance(
fc_calculator: str | None,
fc_calculator_options: str | None,
cutoff_pair_distance: float | None,
symfc_memory_size: float | None,
) -> tuple[float | None, float | None]:
"""Return cutoff_pair_distance from settings."""
_, _fc_calculator_options = get_fc_calculator_params(
fc_calculator,
fc_calculator_options,
cutoff_pair_distance,
)
symfc_options = parse_symfc_options(
extract_fc2_fc3_calculators_options(_fc_calculator_options, 3), 3
)
_cutoff_pair_distance = cutoff_pair_distance
cutoff = symfc_options.get("cutoff")
if cutoff is not None:
_cutoff_pair_distance = cutoff.get(3)
_symfc_memory_size = symfc_memory_size
memsize = symfc_options.get("memsize")
if memsize is not None:
_symfc_memory_size = memsize.get(3)
return _cutoff_pair_distance, _symfc_memory_size

View File

@ -37,15 +37,15 @@
from __future__ import annotations
import dataclasses
from typing import TYPE_CHECKING, Optional
from typing import TYPE_CHECKING, cast
import numpy as np
from numpy.typing import ArrayLike, NDArray
from phonopy.interface.phonopy_yaml import (
PhonopyYaml,
PhonopyYamlDumperBase,
PhonopyYamlLoaderBase,
load_yaml,
phonopy_yaml_property_factory,
)
if TYPE_CHECKING:
@ -60,26 +60,26 @@ from phonopy.structure.symmetry import Symmetry
class Phono3pyYamlData:
"""PhonopyYaml data structure."""
configuration: Optional[dict] = None
calculator: Optional[str] = None
physical_units: Optional[dict] = None
unitcell: Optional[PhonopyAtoms] = None
primitive: Optional[Primitive] = None
supercell: Optional[Supercell] = None
dataset: Optional[dict] = None
supercell_matrix: Optional[np.ndarray] = None
primitive_matrix: Optional[np.ndarray] = None
nac_params: Optional[dict] = None
force_constants: Optional[np.ndarray] = None
symmetry: Optional[Symmetry] = None # symmetry of supercell
frequency_unit_conversion_factor: Optional[float] = None
version: Optional[str] = None
configuration: dict | None = None
calculator: str | None = None
physical_units: dict | None = None
unitcell: PhonopyAtoms | None = None
primitive: Primitive | PhonopyAtoms | None = None
supercell: Supercell | PhonopyAtoms | None = None
dataset: dict | None = None
supercell_matrix: NDArray | None = None
primitive_matrix: NDArray | None = None
nac_params: dict | None = None
force_constants: NDArray | None = None
symmetry: Symmetry | None = None # symmetry of supercell
frequency_unit_conversion_factor: float | None = None
version: str | None = None
command_name: str = "phono3py"
phonon_supercell_matrix: Optional[np.ndarray] = None
phonon_dataset: Optional[dict] = None
phonon_supercell: Optional[Supercell] = None
phonon_primitive: Optional[Primitive] = None
phonon_supercell_matrix: NDArray | None = None
phonon_dataset: dict | None = None
phonon_supercell: Supercell | PhonopyAtoms | None = None
phonon_primitive: Primitive | PhonopyAtoms | None = None
class Phono3pyYamlLoader(PhonopyYamlLoaderBase):
@ -156,10 +156,12 @@ class Phono3pyYamlLoader(PhonopyYamlLoaderBase):
and "phonon_displacements" not in self._yaml
and "displacements" in self._yaml
): # old type1
self._data.phonon_dataset = self._get_dataset(self._data.phonon_supercell)
self._data.phonon_dataset = self._get_dataset(
cast(PhonopyAtoms, self._data.phonon_supercell)
)
else:
self._data.phonon_dataset = self._get_dataset(
self._data.phonon_supercell, key_prefix="phonon_"
cast(PhonopyAtoms, self._data.phonon_supercell), key_prefix="phonon_"
)
def _parse_fc3_dataset(self):
@ -181,7 +183,7 @@ class Phono3pyYamlLoader(PhonopyYamlLoaderBase):
elif isinstance(disp, list): # type2
if "displacement" in disp[0]:
dataset = self._parse_force_sets_type2()
if "displacement_pair_info" in self._yaml:
if "displacement_pair_info" in self._yaml and dataset is not None:
info_yaml = self._yaml["displacement_pair_info"]
if "cutoff_pair_distance" in info_yaml:
dataset["cutoff_distance"] = info_yaml["cutoff_pair_distance"]
@ -296,7 +298,7 @@ class Phono3pyYamlDumper(PhonopyYamlDumperBase):
"dielectric_constant": True,
}
def __init__(self, data: Phono3pyYamlData, dumper_settings=None):
def __init__(self, data: Phono3pyYamlData, dumper_settings: dict | None = None):
"""Init method."""
self._data = data
self._init_dumper_settings(dumper_settings)
@ -402,30 +404,12 @@ class Phono3pyYaml(PhonopyYaml):
default_filenames = ("phono3py_disp.yaml", "phono3py.yaml")
command_name = "phono3py"
configuration = phonopy_yaml_property_factory("configuration")
calculator = phonopy_yaml_property_factory("calculator")
physical_units = phonopy_yaml_property_factory("physical_units")
unitcell = phonopy_yaml_property_factory("unitcell")
primitive = phonopy_yaml_property_factory("primitive")
supercell = phonopy_yaml_property_factory("supercell")
dataset = phonopy_yaml_property_factory("dataset")
supercell_matrix = phonopy_yaml_property_factory("supercell_matrix")
primitive_matrix = phonopy_yaml_property_factory("primitive_matrix")
nac_params = phonopy_yaml_property_factory("nac_params")
force_constants = phonopy_yaml_property_factory("force_constants")
symmetry = phonopy_yaml_property_factory("symmetry")
frequency_unit_conversion_factor = phonopy_yaml_property_factory(
"frequency_unit_conversion_factor"
)
version = phonopy_yaml_property_factory("version")
phonon_supercell_matrix = phonopy_yaml_property_factory("phonon_supercell_matrix")
phonon_dataset = phonopy_yaml_property_factory("phonon_dataset")
phonon_supercell = phonopy_yaml_property_factory("phonon_supercell")
phonon_primitive = phonopy_yaml_property_factory("phonon_primitive")
def __init__(
self, configuration=None, calculator=None, physical_units=None, settings=None
self,
configuration: dict | None = None,
calculator: str | None = None,
physical_units: dict | None = None,
settings: dict | None = None,
):
"""Init method."""
self._data = Phono3pyYamlData(
@ -435,6 +419,193 @@ class Phono3pyYaml(PhonopyYaml):
)
self._dumper_settings = settings
@property
def configuration(self) -> dict | None:
"""Return configuration of phonopy calculation."""
return self._data.configuration
@configuration.setter
def configuration(self, value: dict):
"""Set configuration of phonopy calculation."""
self._data.configuration = value
@property
def calculator(self) -> str | None:
"""Return calculator of phonopy calculation."""
return self._data.calculator
@calculator.setter
def calculator(self, value: str):
"""Set calculator of phonopy calculation."""
self._data.calculator = value
@property
def physical_units(self) -> dict | None:
"""Return physical units of phonopy calculation."""
return self._data.physical_units
@physical_units.setter
def physical_units(self, value: dict):
"""Set physical units of phonopy calculation."""
self._data.physical_units = value
@property
def unitcell(self) -> PhonopyAtoms | None:
"""Return unit cell of phonopy calculation."""
return self._data.unitcell
@unitcell.setter
def unitcell(self, value: PhonopyAtoms):
"""Set unit cell of phonopy calculation."""
self._data.unitcell = value
@property
def primitive(self) -> PhonopyAtoms | None:
"""Return primitive cell of phonopy calculation."""
return self._data.primitive
@primitive.setter
def primitive(self, value: PhonopyAtoms):
"""Set primitive cell of phonopy calculation."""
self._data.primitive = value
@property
def supercell(self) -> PhonopyAtoms | None:
"""Return supercell of phonopy calculation."""
return self._data.supercell
@supercell.setter
def supercell(self, value: PhonopyAtoms):
"""Set supercell of phonopy calculation."""
self._data.supercell = value
@property
def dataset(self) -> dict | None:
"""Return dataset of phonopy calculation."""
return self._data.dataset
@dataset.setter
def dataset(self, value: dict):
"""Set dataset of phonopy calculation."""
self._data.dataset = value
@property
def supercell_matrix(self) -> NDArray | None:
"""Return supercell matrix of phonopy calculation."""
return self._data.supercell_matrix
@supercell_matrix.setter
def supercell_matrix(self, value: ArrayLike):
"""Set supercell matrix of phonopy calculation."""
self._data.supercell_matrix = np.array(value, dtype="intc", order="C")
@property
def primitive_matrix(self) -> NDArray | None:
"""Return primitive matrix of phonopy calculation."""
return self._data.primitive_matrix
@primitive_matrix.setter
def primitive_matrix(self, value: ArrayLike):
"""Set primitive matrix of phonopy calculation."""
self._data.primitive_matrix = np.array(value, dtype="double", order="C")
@property
def nac_params(self) -> dict | None:
"""Return non-analytical term correction parameters."""
return self._data.nac_params
@nac_params.setter
def nac_params(self, value: dict):
"""Set non-analytical term correction parameters."""
if value is not None:
if "born" in value:
value["born"] = np.array(value["born"], dtype="double", order="C")
if "dielectric" in value:
value["dielectric"] = np.array(
value["dielectric"], dtype="double", order="C"
)
self._data.nac_params = value
@property
def force_constants(self) -> NDArray | None:
"""Return force constants of phonopy calculation."""
return self._data.force_constants
@force_constants.setter
def force_constants(self, value: ArrayLike):
"""Set force constants of phonopy calculation."""
self._data.force_constants = np.array(value, dtype="double", order="C")
@property
def symmetry(self) -> Symmetry | None:
"""Return symmetry of phonopy calculation."""
return self._data.symmetry
@symmetry.setter
def symmetry(self, value: Symmetry):
"""Set symmetry of phonopy calculation."""
self._data.symmetry = value
@property
def frequency_unit_conversion_factor(self) -> float | None:
"""Return frequency unit conversion factor."""
return self._data.frequency_unit_conversion_factor
@frequency_unit_conversion_factor.setter
def frequency_unit_conversion_factor(self, value: float):
"""Set frequency unit conversion factor."""
self._data.frequency_unit_conversion_factor = value
@property
def version(self) -> str | None:
"""Return version of phonopy calculation."""
return self._data.version
@version.setter
def version(self, value: str):
"""Set version of phonopy calculation."""
self._data.version = value
@property
def phonon_primitive(self) -> PhonopyAtoms | None:
"""Return phonon primitive cell of phonopy calculation."""
return self._data.phonon_primitive
@phonon_primitive.setter
def phonon_primitive(self, value: PhonopyAtoms):
"""Set phonon primitive cell of phonopy calculation."""
self._data.phonon_primitive = value
@property
def phonon_supercell(self) -> PhonopyAtoms | None:
"""Return phonon supercell of phonopy calculation."""
return self._data.phonon_supercell
@phonon_supercell.setter
def phonon_supercell(self, value: PhonopyAtoms):
"""Set phonon supercell of phonopy calculation."""
self._data.phonon_supercell = value
@property
def phonon_dataset(self) -> dict | None:
"""Return phonon dataset of phonopy calculation."""
return self._data.phonon_dataset
@phonon_dataset.setter
def phonon_dataset(self, value: dict):
"""Set phonon dataset of phonopy calculation."""
self._data.phonon_dataset = value
@property
def phonon_supercell_matrix(self) -> NDArray | None:
"""Return phonon supercell matrix of phonopy calculation."""
return self._data.phonon_supercell_matrix
@phonon_supercell_matrix.setter
def phonon_supercell_matrix(self, value: ArrayLike):
"""Set supercell matrix of phonopy calculation."""
self._data.phonon_supercell_matrix = np.array(value, dtype="intc", order="C")
def __str__(self):
"""Return string text of yaml output."""
ph3yml_dumper = Phono3pyYamlDumper(

View File

@ -36,17 +36,16 @@
from __future__ import annotations
from typing import Optional, Union
import numpy as np
from numpy.typing import ArrayLike
from phonopy.harmonic.dynamical_matrix import get_dynamical_matrix
from phonopy.phonon.tetrahedron_mesh import get_tetrahedra_frequencies
from phonopy.physical_units import get_physical_units
from phonopy.structure.atoms import PhonopyAtoms
from phonopy.structure.atoms import isotope_data as phonopy_isotope_data
from phonopy.structure.cells import Primitive
from phonopy.structure.symmetry import Symmetry
from phonopy.structure.tetrahedron_method import TetrahedronMethod
from phonopy.units import VaspToTHz
from phono3py.other.tetrahedron_method import (
get_integration_weights,
@ -58,9 +57,9 @@ from phono3py.phonon.solver import run_phonon_solver_c, run_phonon_solver_py
def get_mass_variances(
primitive: Optional[PhonopyAtoms] = None,
symbols: Optional[Union[list[str], tuple[str]]] = None,
isotope_data: Optional[dict] = None,
primitive: PhonopyAtoms | None = None,
symbols: list[str] | tuple[str] | None = None,
isotope_data: dict | None = None,
):
"""Calculate mass variances."""
if primitive is not None:
@ -93,14 +92,14 @@ class Isotope:
def __init__(
self,
mesh,
primitive,
mesh: float | ArrayLike,
primitive: Primitive,
mass_variances=None, # length of list is num_atom.
isotope_data=None,
band_indices=None,
sigma=None,
bz_grid=None,
frequency_factor_to_THz=VaspToTHz,
bz_grid: BZGrid | None = None,
frequency_factor_to_THz: float | None = None,
use_grg=False,
symprec=1e-5,
cutoff_frequency=None,
@ -116,13 +115,15 @@ class Isotope:
self._mass_variances = np.array(mass_variances, dtype="double")
self._primitive = primitive
self._sigma = sigma
self._bz_grid = bz_grid
self._symprec = symprec
if cutoff_frequency is None:
self._cutoff_frequency = 0
else:
self._cutoff_frequency = cutoff_frequency
self._frequency_factor_to_THz = frequency_factor_to_THz
if frequency_factor_to_THz is None:
self._frequency_factor_to_THz = get_physical_units().DefaultToTHz
else:
self._frequency_factor_to_THz = frequency_factor_to_THz
self._lapack_zheev_uplo = lapack_zheev_uplo
self._nac_q_direction = None
@ -140,7 +141,7 @@ class Isotope:
else:
self._band_indices = np.array(band_indices, dtype="int64")
if self._bz_grid is None:
if bz_grid is None:
primitive_symmetry = Symmetry(self._primitive, self._symprec)
self._bz_grid = BZGrid(
self._mesh,
@ -149,6 +150,8 @@ class Isotope:
use_grg=use_grg,
store_dense_gp_map=True,
)
else:
self._bz_grid = bz_grid
def set_grid_point(self, grid_point):
"""Initialize grid points."""
@ -193,8 +196,9 @@ class Isotope:
return self._gamma
@property
def bz_grid(self):
def bz_grid(self) -> BZGrid:
"""Return BZgrid class instance."""
assert self._bz_grid is not None
return self._bz_grid
@property

View File

@ -35,7 +35,7 @@
# POSSIBILITY OF SUCH DAMAGE.
import numpy as np
from phonopy.units import AMU, EV, Angstrom, Hbar, Kb, THz, THzToEv
from phonopy.physical_units import get_physical_units
def gaussian(x, sigma):
@ -62,7 +62,9 @@ def bose_einstein(x, T):
Temperature in K
"""
return 1.0 / (np.exp(THzToEv * x / (Kb * T)) - 1)
return 1.0 / (
np.exp(get_physical_units().THzToEv * x / (get_physical_units().KB * T)) - 1
)
def sigma_squared(x, T):
@ -96,7 +98,13 @@ def sigma_squared(x, T):
n = bose_einstein(x, T)
# factor=1.0107576777968994
factor = Hbar * EV / (2 * np.pi * THz) / AMU / Angstrom**2
factor = (
get_physical_units().Hbar
* get_physical_units().EV
/ (2 * np.pi * get_physical_units().THz)
/ get_physical_units().AMU
/ get_physical_units().Angstrom ** 2
)
#########################
np.seterr(**old_settings)

View File

@ -39,12 +39,14 @@ from __future__ import annotations
import warnings
from collections.abc import Sequence
from numpy.typing import ArrayLike, NDArray
try:
from spglib import SpglibDataset
from spglib import SpglibDataset # type: ignore
except ImportError:
from types import SimpleNamespace as SpglibDataset
from types import SimpleNamespace
from typing import Optional, Union
import numpy as np
@ -84,7 +86,7 @@ class BZGrid:
The grid systems with (BZ-grid, BZG) and without (GR-grid, GRG) BZ surface
are mutually related up to modulo D_diag. More precisely the conversion
of grid adresses are performed as follows:
of grid addresses are performed as follows:
From BZG to GRG
gr_gp = get_grid_point_from_address(bz_grid.addresses[bz_gp], D_diag)
@ -103,12 +105,12 @@ class BZGrid:
Recovering reduced coordinates
------------------------------
q-points with respect to the original recirpocal
q-points with respect to the original reciprocal
basis vectors are given by
q = np.dot(Q, addresses[gp] / D_diag.astype('double'))
for the Gamma cetnred grid. With shifted, where only half grid shifts
for the Gamma centred grid. With shifted, where only half grid shifts
that satisfy the symmetry are considered,
q = np.dot(Q, (addresses[gp] + np.dot(P, s)) / D_diag.astype('double'))
@ -132,6 +134,7 @@ class BZGrid:
D_diag : ndarray
P : ndarray
Q : ndarray
PS : ndarray
QDinv : ndarray
grid_matrix : ndarray
microzone_lattice : ndarray
@ -141,12 +144,12 @@ class BZGrid:
def __init__(
self,
mesh: Union[int, float, Sequence, np.ndarray],
reciprocal_lattice=None,
lattice=None,
symmetry_dataset: Optional[Union[SpglibDataset]] = None,
transformation_matrix: Optional[Union[Sequence, np.ndarray]] = None,
is_shift: Optional[Union[list, np.ndarray]] = None,
mesh: float | ArrayLike,
reciprocal_lattice: ArrayLike | None = None,
lattice: ArrayLike | None = None,
symmetry_dataset: SpglibDataset | None = None,
transformation_matrix: ArrayLike | None = None,
is_shift: ArrayLike | None = None,
is_time_reversal: bool = True,
use_grg: bool = False,
force_SNF: bool = False,
@ -202,17 +205,18 @@ class BZGrid:
self._is_shift = [v * 1 for v in is_shift]
self._is_time_reversal = is_time_reversal
self._store_dense_gp_map = store_dense_gp_map
self._addresses = None
self._gp_map = None
self._addresses: np.ndarray
self._gp_map: np.ndarray
self._grid_matrix = None
self._D_diag = np.ones(3, dtype="int64")
self._Q = np.eye(3, dtype="int64", order="C")
self._P = np.eye(3, dtype="int64", order="C")
self._QDinv = None
self._microzone_lattice = None
self._rotations = None
self._reciprocal_operations = None
self._gp_Gamma = None
self._QDinv: np.ndarray
self._microzone_lattice: np.ndarray
self._rotations: np.ndarray
self._reciprocal_operations: np.ndarray
self._rotations_cartesian: np.ndarray
self._gp_Gamma: int
if reciprocal_lattice is not None:
self._reciprocal_lattice = np.array(
@ -281,7 +285,7 @@ class BZGrid:
return np.array(np.dot(self.P, self._is_shift), dtype="int64")
@property
def grid_matrix(self):
def grid_matrix(self) -> Optional[np.ndarray]:
"""Grid generating matrix to be represented by SNF.
Grid generating matrix used for SNF.
@ -292,7 +296,7 @@ class BZGrid:
return self._grid_matrix
@property
def addresses(self):
def addresses(self) -> np.ndarray:
"""BZ-grid addresses.
Integer grid address of the points in Brillouin zone including
@ -315,7 +319,7 @@ class BZGrid:
return self._gp_map
@property
def gp_Gamma(self):
def gp_Gamma(self) -> int:
"""Return grid point index of Gamma-point."""
return self._gp_Gamma
@ -345,7 +349,7 @@ class BZGrid:
return self._grg2bzg
@property
def microzone_lattice(self):
def microzone_lattice(self) -> np.ndarray:
"""Basis vectors of microzone.
Basis vectors of microzone of GR-grid in column vectors.
@ -354,6 +358,16 @@ class BZGrid:
"""
return self._microzone_lattice
@property
def reciprocal_lattice(self) -> np.ndarray:
"""Reciprocal basis vectors of primitive cell.
Reciprocal basis vectors of primitive cell in column vectors.
shape=(3, 3), dtype='double', order='C'.
"""
return self._reciprocal_lattice
@property
def store_dense_gp_map(self):
"""Return gp_map type.
@ -364,7 +378,7 @@ class BZGrid:
return self._store_dense_gp_map
@property
def rotations(self):
def rotations(self) -> np.ndarray:
"""Return rotation matrices for grid points.
Rotation matrices for GR-grid addresses (g) defined as g'=Rg. This can
@ -376,12 +390,12 @@ class BZGrid:
return self._rotations
@property
def rotations_cartesian(self):
def rotations_cartesian(self) -> np.ndarray:
"""Return rotations in Cartesian coordinates."""
return self._rotations_cartesian
@property
def reciprocal_operations(self):
def reciprocal_operations(self) -> np.ndarray:
"""Return reciprocal rotations.
Reciprocal space rotation matrices in fractional coordinates defined as
@ -392,7 +406,7 @@ class BZGrid:
return self._reciprocal_operations
@property
def symmetry_dataset(self) -> SpglibDataset:
def symmetry_dataset(self) -> Optional[SpglibDataset]:
"""Return Symmetry.dataset."""
return self._symmetry_dataset
@ -539,7 +553,7 @@ class GridMatrix:
mesh: Union[int, float, Sequence, np.ndarray],
lattice: Union[Sequence, np.ndarray],
symmetry_dataset: Optional[SpglibDataset] = None,
transformation_matrix: Optional[Union[list, np.ndarray]] = None,
transformation_matrix: Optional[Union[Sequence, np.ndarray]] = None,
use_grg: bool = True,
force_SNF: bool = False,
SNF_coordinates: str = "reciprocal",
@ -591,7 +605,7 @@ class GridMatrix:
)
@property
def grid_matrix(self):
def grid_matrix(self) -> Optional[np.ndarray]:
"""Grid generating matrix to be represented by SNF.
Grid generating matrix used for SNF.
@ -602,7 +616,7 @@ class GridMatrix:
return self._grid_matrix
@property
def D_diag(self):
def D_diag(self) -> np.ndarray:
"""Diagonal elements of diagonal matrix after SNF: D=PAQ.
This corresponds to the mesh numbers in transformed reciprocal
@ -637,7 +651,7 @@ class GridMatrix:
mesh: Union[int, float, Sequence, np.ndarray],
use_grg: bool = False,
symmetry_dataset: Optional[SpglibDataset] = None,
transformation_matrix: Optional[Union[list, np.ndarray]] = None,
transformation_matrix: Optional[Union[Sequence, np.ndarray]] = None,
force_SNF=False,
coordinates="reciprocal",
) -> None:
@ -665,9 +679,8 @@ class GridMatrix:
have similar lengths.
"""
num_values = len(np.ravel(mesh))
if num_values == 1:
length = float(mesh)
try:
length = float(mesh) # type: ignore
if use_grg:
found_grg = self._run_grg(
symmetry_dataset,
@ -685,17 +698,20 @@ class GridMatrix:
length, self._lattice, rotations=symmetry_dataset.rotations
)
self._D_diag = np.array(mesh_numbers, dtype="int64")
if num_values == 9:
self._run_grg(
symmetry_dataset,
transformation_matrix,
None,
mesh,
force_SNF,
coordinates,
)
if num_values == 3:
self._D_diag = np.array(mesh, dtype="int64")
except (ValueError, TypeError):
num_values = len(np.ravel(mesh))
if num_values == 9:
self._run_grg(
symmetry_dataset,
transformation_matrix,
None,
mesh,
force_SNF,
coordinates,
)
if num_values == 3:
self._D_diag = np.array(mesh, dtype="int64")
def _run_grg(
self,
@ -730,7 +746,7 @@ class GridMatrix:
)
return False
def _get_mock_symmetry_dataset(self, transformation_matrix) -> dict:
def _get_mock_symmetry_dataset(self, transformation_matrix) -> SimpleNamespace:
"""Return mock symmetry_dataset containing transformation matrix.
Assuming self._lattice as standardized cell, and inverse of
@ -753,8 +769,6 @@ class GridMatrix:
)
raise RuntimeError(msg)
from types import SimpleNamespace
sym_dataset = SimpleNamespace(
**{
"rotations": np.eye(3, dtype="intc", order="C").reshape(1, 3, 3),
@ -768,7 +782,7 @@ class GridMatrix:
def _set_GRG_mesh(
self,
sym_dataset: SpglibDataset,
sym_dataset: Union[SpglibDataset, SimpleNamespace],
length: Optional[float] = None,
grid_matrix=None,
force_SNF=False,
@ -802,11 +816,14 @@ class GridMatrix:
self._grid_matrix = _grid_matrix
def _get_grid_matrix(
self, sym_dataset: dict, length: float, coordinates: str = "reciprocal"
self,
sym_dataset: Union[SpglibDataset, SimpleNamespace],
length: float,
coordinates: str = "reciprocal",
):
"""Return grid matrix.
Grid is generated by the distance `length`. `coordinates` is used eighter
Grid is generated by the distance `length`. `coordinates` is used either
the grid is defined by supercell in real space or mesh grid in reciprocal
space.
@ -855,6 +872,22 @@ class GridMatrix:
return grid_matrix
def get_qpoints_from_bz_grid_points(
gps: Union[int, np.ndarray], bz_grid: BZGrid
) -> np.ndarray:
"""Return q-point(s) in reduced coordinates of grid point(s).
Parameters
----------
i_gps : int or ndarray
BZ-grid index (int) or indices (ndarray).
bz_grid : BZGrid
BZ-grid instance.
"""
return bz_grid.addresses[gps] @ bz_grid.QDinv.T
def get_grid_point_from_address_py(addresses, D_diag):
"""Return GR-grid point index from addresses.
@ -1041,12 +1074,12 @@ def _get_grid_points_by_bz_rotations_py(bz_gp, bz_grid: BZGrid, rotations):
)
+ num_grgp
).tolist()
gps.insert(0, gp)
gps.insert(0, gp) # type: ignore
indices = np.where((bz_grid.addresses[gps] == adrs).all(axis=1))[0]
if len(indices) == 0:
msg = "with_surface did not work properly."
raise RuntimeError(msg)
bzgps[i] = gps[indices[0]]
bzgps[i] = gps[indices[0]] # type: ignore
return bzgps
@ -1125,7 +1158,7 @@ def _relocate_BZ_grid_address(
The translationally equivalent grid points corresponding to one grid point
on BZ surface are stored in continuously. If the multiplicity (number of
equivalent grid points) is 1, 2, 1, 4, ... for the grid points,
``bz_map`` stores the multiplicites and the index positions of the first
``bz_map`` stores the multiplicities and the index positions of the first
grid point of the equivalent grid points, i.e.,
bz_map[:] = [0, 1, 3, 4, 8...]
@ -1151,21 +1184,15 @@ def _relocate_BZ_grid_address(
else:
bz_map = np.zeros(np.prod(D_diag) * 9 + 1, dtype="int64")
# Mpr^-1 = Lr^-1 Lp
reclat_T = np.array(np.transpose(reciprocal_lattice), dtype="double", order="C")
reduced_basis = get_reduced_bases(reclat_T)
tmat_inv = np.dot(np.linalg.inv(reduced_basis.T), reclat_T.T)
tmat_inv_int = np.rint(tmat_inv).astype("int64")
assert (np.abs(tmat_inv - tmat_inv_int) < 1e-5).all()
reduced_basis, tmat_inv_int = get_reduced_bases_and_tmat_inv(reciprocal_lattice)
num_gp = recgrid.bz_grid_addresses(
bz_grid_addresses,
bz_map,
bzg2grg,
np.array(D_diag, dtype="int64"),
np.array(np.dot(tmat_inv_int, Q), dtype="int64", order="C"),
np.array(tmat_inv_int @ Q, dtype="int64", order="C"),
_PS,
np.array(reduced_basis.T, dtype="double", order="C"),
reduced_basis,
store_dense_gp_map * 1 + 1,
)
@ -1174,6 +1201,39 @@ def _relocate_BZ_grid_address(
return bz_grid_addresses, bz_map, bzg2grg
def get_reduced_bases_and_tmat_inv(
reciprocal_lattice: ArrayLike,
) -> tuple[NDArray, NDArray]:
"""Return reduced bases and inverse transformation matrix.
Parameters
----------
reciprocal_lattice : ArrayLike
Reciprocal lattice vectors in column vectors.
shape=(3, 3), dtype='double'
Returns
-------
reduced_basis : ndarray
Reduced basis vectors in column vectors.
shape=(3, 3), dtype='double', order='C'
tmat_inv_int : ndarray
Inverse transformation matrix in integer.
This is used to transform reciprocal lattice vectors to
conventional lattice vectors.
shape=(3, 3), dtype='int64'
"""
# Mpr^-1 = Lr^-1 Lp
reclat_T = np.array(np.transpose(reciprocal_lattice), dtype="double", order="C")
reduced_basis = get_reduced_bases(reclat_T)
assert reduced_basis is not None, "Reduced basis is not found."
tmat_inv = np.linalg.inv(reduced_basis.T) @ reclat_T.T
tmat_inv_int = np.rint(tmat_inv).astype("int64")
assert (np.abs(tmat_inv - tmat_inv_int) < 1e-5).all()
return np.array(reduced_basis.T, dtype="double", order="C"), tmat_inv_int
def _get_ir_grid_map(
D_diag: Union[np.ndarray, Sequence],
grg_rotations: Union[np.ndarray, Sequence],

View File

@ -37,12 +37,11 @@
import numpy as np
from phonopy.phonon.degeneracy import degenerate_sets
from phonopy.phonon.group_velocity import GroupVelocity
from phonopy.units import VaspToTHz
from phonopy.utils import similarity_transformation
class GroupVelocityMatrix(GroupVelocity):
"""Class to calculate group velocities matricies of phonons.
"""Class to calculate group velocities matrices of phonons.
v_qjj' = 1/(2*sqrt(omega_qj*omega_qj')) * <e(q,j)|dD/dq|e(q,j')>
@ -57,7 +56,7 @@ class GroupVelocityMatrix(GroupVelocity):
dynamical_matrix,
q_length=None,
symmetry=None,
frequency_factor_to_THz=VaspToTHz,
frequency_factor_to_THz=None,
cutoff_frequency=1e-4,
):
"""Init method.

View File

@ -36,7 +36,7 @@
import numpy as np
from phonopy.phonon.thermal_properties import mode_cv
from phonopy.units import Kb
from phonopy.physical_units import get_physical_units
def mode_cv_matrix(temp, freqs, cutoff=1e-4):
@ -67,7 +67,8 @@ def mode_cv_matrix(temp, freqs, cutoff=1e-4):
shape=(num_band, num_band), dtype='double', order='C'.
"""
x = freqs / Kb / temp
KB = get_physical_units().KB
x = freqs / KB / temp
shape = (len(freqs), len(freqs))
cvm = np.zeros(shape, dtype="double", order="C")
for i, j in np.ndindex(shape):
@ -77,5 +78,5 @@ def mode_cv_matrix(temp, freqs, cutoff=1e-4):
sub = x[i] - x[j]
add = x[i] + x[j]
n_inv = np.exp([x[i], x[j], sub]) - 1
cvm[i, j] = Kb * n_inv[2] / sub * (add / 2) ** 2 / n_inv[0] * (1 / n_inv[1] + 1)
cvm[i, j] = KB * n_inv[2] / sub * (add / 2) ** 2 / n_inv[0] * (1 / n_inv[1] + 1)
return cvm

View File

@ -34,9 +34,16 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import annotations
import numpy as np
from phonopy.harmonic.dynamical_matrix import (
DynamicalMatrix,
DynamicalMatrixGL,
DynamicalMatrixNAC,
)
from phonopy.physical_units import get_physical_units
from phonopy.structure.cells import sparse_to_dense_svecs
from phonopy.units import VaspToTHz
def run_phonon_solver_c(
@ -47,15 +54,15 @@ def run_phonon_solver_c(
grid_points,
grid_address,
QDinv,
frequency_conversion_factor=VaspToTHz,
frequency_conversion_factor=None,
nac_q_direction=None, # in reduced coordinates
lapack_zheev_uplo="L",
):
"""Bulid and solve dynamical matrices on grid in C-API.
"""Build and solve dynamical matrices on grid in C-API.
Note
----
When LAPACKE is linked in C, `phononcalc.phonons_at_gridpoints` constucts
When LAPACKE is linked in C, `phononcalc.phonons_at_gridpoints` constructs
and solves dynamical matrices on grid points. Otherwise, it only constructs
dynamical matrices and solves them in python.
@ -73,7 +80,7 @@ def run_phonon_solver_c(
QDinv : ndarray
See BZGrid.QDinv.
frequency_conversion_factor : float, optional
Frequency convertion factor that is multiplied with sqrt or eigenvalue
Frequency conversion factor that is multiplied with sqrt or eigenvalue
of dynamical matrix. Default is VaspToTHz.
nac_q_direction : array_like, optional
See Interaction.nac_q_direction. Default is None.
@ -81,8 +88,13 @@ def run_phonon_solver_c(
'U' or 'L' for lapack zheev solver. Default is 'L'.
"""
import phono3py._phono3py as phono3c
import phono3py._phononcalc as phononcalc
import phono3py._phono3py as phono3c # type: ignore[import-untyped]
import phono3py._phononcalc as phononcalc # type: ignore[import-untyped]
if frequency_conversion_factor is None:
_frequency_conversion_factor = get_physical_units().DefaultToTHz
else:
_frequency_conversion_factor = frequency_conversion_factor
(
svecs,
@ -95,7 +107,7 @@ def run_phonon_solver_c(
dielectric,
) = _extract_params(dm)
if dm.is_nac() and dm.nac_method == "gonze":
if isinstance(dm, DynamicalMatrixGL):
gonze_nac_dataset = dm.Gonze_nac_dataset
if gonze_nac_dataset[0] is None:
dm.make_Gonze_nac_dataset()
@ -107,6 +119,7 @@ def run_phonon_solver_c(
G_list, # List of G points where d-d interactions are integrated.
Lambda,
) = gonze_nac_dataset # Convergence parameter
assert Lambda is not None
fc = gonze_fc
use_GL_NAC = True
else:
@ -115,7 +128,7 @@ def run_phonon_solver_c(
dd_q0 = np.zeros(2) # dummy variable
G_list = np.zeros(3) # dummy variable
Lambda = 0 # dummy variable
if not dm.is_nac():
if not isinstance(dm, DynamicalMatrixNAC):
born = np.zeros((3, 3)) # dummy variable
dielectric = np.zeros(3) # dummy variable
fc = dm.force_constants
@ -154,7 +167,7 @@ def run_phonon_solver_c(
masses,
fc_p2s,
fc_s2p,
frequency_conversion_factor,
_frequency_conversion_factor,
born,
dielectric,
rec_lattice,
@ -163,7 +176,7 @@ def run_phonon_solver_c(
dd_q0,
G_list,
float(Lambda),
dm.is_nac() * 1,
isinstance(dm, DynamicalMatrixNAC) * 1,
is_nac_q_zero * 1,
use_GL_NAC * 1,
lapack_zheev_uplo,
@ -179,7 +192,7 @@ def run_phonon_solver_c(
frequencies[phonon_undone] = (
np.sign(frequencies[phonon_undone])
* np.sqrt(np.abs(frequencies[phonon_undone]))
* frequency_conversion_factor
* _frequency_conversion_factor
)
@ -194,7 +207,7 @@ def run_phonon_solver_py(
frequency_conversion_factor,
lapack_zheev_uplo,
):
"""Bulid and solve dynamical matrices on grid in python."""
"""Build and solve dynamical matrices on grid in python."""
gp = grid_point
if phonon_done[gp] == 0:
phonon_done[gp] = 1
@ -202,14 +215,14 @@ def run_phonon_solver_py(
dynamical_matrix.run(q)
dm = dynamical_matrix.dynamical_matrix
eigvals, eigvecs = np.linalg.eigh(dm, UPLO=lapack_zheev_uplo)
eigvals = eigvals.real
eigvals = eigvals.real # type: ignore[no-untyped-call]
frequencies[gp] = (
np.sqrt(np.abs(eigvals)) * np.sign(eigvals) * frequency_conversion_factor
)
eigenvectors[gp] = eigvecs
def _extract_params(dm):
def _extract_params(dm: DynamicalMatrix | DynamicalMatrixNAC):
svecs, multi = dm.primitive.get_smallest_vectors()
if dm.primitive.store_dense_svecs:
_svecs = svecs
@ -220,7 +233,7 @@ def _extract_params(dm):
masses = np.array(dm.primitive.masses, dtype="double")
rec_lattice = np.array(np.linalg.inv(dm.primitive.cell), dtype="double", order="C")
positions = np.array(dm.primitive.positions, dtype="double", order="C")
if dm.is_nac():
if isinstance(dm, DynamicalMatrixNAC):
born = dm.born
nac_factor = dm.nac_factor
dielectric = dm.dielectric_constant

View File

@ -35,8 +35,9 @@
# POSSIBILITY OF SUCH DAMAGE.
import numpy as np
from phonopy.harmonic.dynamical_matrix import DynamicalMatrixGL
from phonopy.phonon.group_velocity import GroupVelocity
from phonopy.units import VaspToTHz
from phonopy.physical_units import get_physical_units
class VelocityOperator(GroupVelocity):
@ -47,7 +48,7 @@ class VelocityOperator(GroupVelocity):
dynamical_matrix,
q_length=None,
symmetry=None,
frequency_factor_to_THz=VaspToTHz,
frequency_factor_to_THz=None,
cutoff_frequency=1e-4,
):
"""Init method.
@ -75,7 +76,10 @@ class VelocityOperator(GroupVelocity):
if self._q_length is None:
self._q_length = 5e-6
self._symmetry = symmetry
self._factor = frequency_factor_to_THz
if frequency_factor_to_THz is None:
self._factor = get_physical_units().DefaultToTHz
else:
self._factor = frequency_factor_to_THz
self._cutoff_frequency = cutoff_frequency
self._directions = np.array(
@ -143,7 +147,7 @@ class VelocityOperator(GroupVelocity):
# computed along several directions
ddms = self._get_dsqrtD_FD(np.array(q))
#
# ddms[0] cointains the FD derivative in the direction in which the velocity
# ddms[0] contains the FD derivative in the direction in which the velocity
# operator is diagonalized
for id_dir in range(0, 3):
gv_operator[:, :, id_dir] = (
@ -207,11 +211,7 @@ class VelocityOperator(GroupVelocity):
if np.linalg.norm(q) < np.linalg.norm(delta_q):
flag_gamma = True
if (
(self._dynmat.is_nac())
and (self._dynmat.nac_method == "gonze")
and flag_gamma
):
if isinstance(dynmat, DynamicalMatrixGL) and flag_gamma:
dynmat.run(
q - delta_q, q_direction=(q - delta_q) / np.linalg.norm(q - delta_q)
)

View File

@ -37,7 +37,7 @@
from typing import Optional
import numpy as np
from phonopy.units import Kb, THzToEv
from phonopy.physical_units import get_physical_units
from phono3py.phonon3.imag_self_energy import ImagSelfEnergy
from phono3py.phonon3.interaction import Interaction
@ -164,7 +164,7 @@ class CollisionMatrix(ImagSelfEnergy):
self._ir_map_at_q,
self._rot_grid_points, # in GRGrid
self._rotations_cartesian,
self._temperature,
self._temperature * get_physical_units().KB / get_physical_units().THzToEv,
self._unit_conversion,
self._cutoff_frequency,
)
@ -180,7 +180,7 @@ class CollisionMatrix(ImagSelfEnergy):
self._triplets_at_q,
self._triplets_map_at_q,
self._ir_map_at_q,
self._temperature,
self._temperature * get_physical_units().KB / get_physical_units().THzToEv,
self._unit_conversion,
self._cutoff_frequency,
)
@ -251,7 +251,7 @@ class CollisionMatrix(ImagSelfEnergy):
"""Return mapping table from grid point index to triplet index.
triplets_map_at_q contains index mapping of q1 in (q0, q1, q2) to
independet q1 under q0+q1+q2=G with a fixed q0.
independent q1 under q0+q1+q2=G with a fixed q0.
Note
----
@ -311,7 +311,11 @@ class CollisionMatrix(ImagSelfEnergy):
freqs = self._frequencies[gp]
sinh = np.where(
freqs > self._cutoff_frequency,
np.sinh(freqs * THzToEv / (2 * Kb * self._temperature)),
np.sinh(
freqs
* get_physical_units().THzToEv
/ (2 * get_physical_units().KB * self._temperature)
),
-1.0,
)
inv_sinh = np.where(sinh > 0, 1.0 / sinh, 0)

View File

@ -34,6 +34,10 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import annotations
from typing import Literal
import numpy as np
from phonopy.harmonic.displacement import (
directions_axis,
@ -131,9 +135,12 @@ def direction_to_displacement(
def get_third_order_displacements(
cell: PhonopyAtoms, symmetry: Symmetry, is_plusminus="auto", is_diagonal=False
cell: PhonopyAtoms,
symmetry: Symmetry,
is_plusminus: bool | Literal["auto"] = "auto",
is_diagonal: bool = False,
):
"""Create dispalcement dataset.
"""Create displacement dataset.
Note
----
@ -143,7 +150,7 @@ def get_third_order_displacements(
between Atoms 1, 2, and 3 is calculated.
Atom 2: The second displaced atom. Second order force constant
between Atoms 2 and 3 is calculated.
Atom 3: Force is mesuared on this atom.
Atom 3: Force is measured on this atom.
Parameters
----------

View File

@ -34,19 +34,22 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import annotations
import logging
import sys
import numpy as np
from numpy.typing import NDArray
from phonopy.harmonic.force_constants import (
distribute_force_constants,
get_fc2,
get_nsym_list_and_s2pp,
get_positions_sent_by_rot_inv,
get_rotated_displacement,
similarity_transformation,
solve_force_constants,
)
from phonopy.interface.fc_calculator import get_fc2
from phonopy.structure.atoms import PhonopyAtoms
from phonopy.structure.cells import Primitive, compute_all_sg_permutations
from phonopy.structure.symmetry import Symmetry
@ -84,7 +87,13 @@ def get_fc3(
"""
# fc2 has to be full matrix to compute delta-fc2
# p2s_map elements are extracted if is_compact_fc=True at the last part.
fc2 = get_fc2(supercell, symmetry, disp_dataset)
fc2 = get_fc2(
supercell,
disp_dataset,
primitive=primitive,
is_compact_fc=False,
symmetry=symmetry,
)
fc3 = _get_fc3_least_atoms(
supercell,
primitive,
@ -567,30 +576,50 @@ def cutoff_fc3_by_zero(fc3, supercell, cutoff_distance, p2s_map=None, symprec=1e
break
def show_drift_fc3(fc3, primitive=None, name="fc3"):
"""Show drift of fc3."""
def show_drift_fc3(
fc3: NDArray, primitive: Primitive | None = None, name: str = "fc3", digit: int = 8
):
"""Show max drift of fc3."""
maxval1, maxval2, maxval3, xyz1, xyz2, xyz3 = get_drift_fc3(
fc3, primitive=primitive
)
text = f"Max drift of {name}: "
text += f"{maxval1:.{digit}f} ({'xyz'[xyz1[0]]}{'xyz'[xyz1[1]]}{'xyz'[xyz1[2]]}) "
text += f"{maxval2:.{digit}f} ({'xyz'[xyz2[0]]}{'xyz'[xyz2[1]]}{'xyz'[xyz2[2]]}) "
text += f"{maxval3:.{digit}f} ({'xyz'[xyz3[0]]}{'xyz'[xyz3[1]]}{'xyz'[xyz3[2]]})"
print(text)
def get_drift_fc3(
fc3: NDArray, primitive: Primitive | None = None
) -> tuple[float, float, float, list[int], list[int], list[int]]:
"""Return max drift of fc3."""
if fc3.shape[0] == fc3.shape[1]:
num_atom = fc3.shape[0]
maxval1 = 0
maxval2 = 0
maxval3 = 0
klm1 = [0, 0, 0]
klm2 = [0, 0, 0]
klm3 = [0, 0, 0]
xyz1 = [0, 0, 0]
xyz2 = [0, 0, 0]
xyz3 = [0, 0, 0]
for i, j, k, ll, m in list(np.ndindex((num_atom, num_atom, 3, 3, 3))):
val1 = fc3[:, i, j, k, ll, m].sum()
val2 = fc3[i, :, j, k, ll, m].sum()
val3 = fc3[i, j, :, k, ll, m].sum()
if abs(val1) > abs(maxval1):
maxval1 = val1
klm1 = [k, ll, m]
xyz1 = [k, ll, m]
if abs(val2) > abs(maxval2):
maxval2 = val2
klm2 = [k, ll, m]
xyz2 = [k, ll, m]
if abs(val3) > abs(maxval3):
maxval3 = val3
klm3 = [k, ll, m]
xyz3 = [k, ll, m]
else:
if primitive is None:
raise RuntimeError(
"Primitive cell is required to get drift of compact fc3."
)
try:
import phono3py._phono3py as phono3c
@ -608,9 +637,9 @@ def show_drift_fc3(fc3, primitive=None, name="fc3"):
maxval1 = 0
maxval2 = 0
maxval3 = 0
klm1 = [0, 0, 0]
klm2 = [0, 0, 0]
klm3 = [0, 0, 0]
xyz1 = [0, 0, 0]
xyz2 = [0, 0, 0]
xyz3 = [0, 0, 0]
phono3c.transpose_compact_fc3(
fc3, permutations, s2pp_map, p2s_map, nsym_list, 0
) # dim[0] <--> dim[1]
@ -618,7 +647,7 @@ def show_drift_fc3(fc3, primitive=None, name="fc3"):
val1 = fc3[i, :, j, k, ll, m].sum()
if abs(val1) > abs(maxval1):
maxval1 = val1
klm1 = [k, ll, m]
xyz1 = [k, ll, m]
phono3c.transpose_compact_fc3(
fc3, permutations, s2pp_map, p2s_map, nsym_list, 0
) # dim[0] <--> dim[1]
@ -627,10 +656,10 @@ def show_drift_fc3(fc3, primitive=None, name="fc3"):
val3 = fc3[i, j, :, k, ll, m].sum()
if abs(val2) > abs(maxval2):
maxval2 = val2
klm2 = [k, ll, m]
xyz2 = [k, ll, m]
if abs(val3) > abs(maxval3):
maxval3 = val3
klm3 = [k, ll, m]
xyz3 = [k, ll, m]
except ImportError as exc:
text = (
"Import error at phono3c.tranpose_compact_fc3. "
@ -638,11 +667,7 @@ def show_drift_fc3(fc3, primitive=None, name="fc3"):
)
raise RuntimeError(text) from exc
text = "Max drift of %s: " % name
text += "%f (%s%s%s) " % (maxval1, "xyz"[klm1[0]], "xyz"[klm1[1]], "xyz"[klm1[2]])
text += "%f (%s%s%s) " % (maxval2, "xyz"[klm2[0]], "xyz"[klm2[1]], "xyz"[klm2[2]])
text += "%f (%s%s%s)" % (maxval3, "xyz"[klm3[0]], "xyz"[klm3[1]], "xyz"[klm3[2]])
print(text)
return maxval1, maxval2, maxval3, xyz1, xyz2, xyz3
def _set_permutation_symmetry_fc3_elem_with_cutoff(fc3, fc3_done, a, b, c):

View File

@ -37,11 +37,15 @@
import sys
import numpy as np
from phonopy.harmonic.dynamical_matrix import get_dynamical_matrix
from phonopy.harmonic.dynamical_matrix import (
DynamicalMatrixGL,
DynamicalMatrixNAC,
get_dynamical_matrix,
)
from phonopy.physical_units import get_physical_units
from phonopy.structure.atoms import PhonopyAtoms
from phonopy.structure.cells import Primitive
from phonopy.structure.grid_points import get_qpoints
from phonopy.units import VaspToTHz
def run_gruneisen_parameters(
@ -96,8 +100,8 @@ def run_gruneisen_parameters(
if log_level > 0:
dm = gruneisen.dynamical_matrix
if dm.is_nac() and dm.nac_method == "gonze":
dm.show_Gonze_nac_message()
if isinstance(dm, DynamicalMatrixGL):
dm.show_nac_message()
if mesh is not None:
gruneisen.set_sampling_mesh(mesh, rotations=rotations, is_gamma_center=True)
@ -122,7 +126,7 @@ def run_gruneisen_parameters(
class Gruneisen:
"""Calculat mode Grueneisen parameters from fc3."""
"""Calculate mode Grueneisen parameters from fc3."""
def __init__(
self,
@ -133,7 +137,7 @@ class Gruneisen:
nac_params=None,
nac_q_direction=None,
ion_clamped=False,
factor=VaspToTHz,
factor=None,
symprec=1e-5,
):
"""Init method."""
@ -142,7 +146,10 @@ class Gruneisen:
self._scell = supercell
self._pcell = primitive
self._ion_clamped = ion_clamped
self._factor = factor
if factor is None:
self._factor = get_physical_units().DefaultToTHz
else:
self._factor = factor
self._symprec = symprec
self._dm = get_dynamical_matrix(
self._fc2,
@ -307,7 +314,7 @@ class Gruneisen:
gruneisen_parameters = []
frequencies = []
for i, q in enumerate(qpoints):
if self._dm.is_nac():
if isinstance(self._dm, DynamicalMatrixNAC):
if (np.abs(q) < 1e-5).all(): # If q is almost at Gamma
if self._run_mode == "band":
# Direction estimated from neighboring point

View File

@ -34,13 +34,16 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import annotations
import sys
import warnings
from typing import List, Optional
from collections.abc import Sequence
import numpy as np
from numpy.typing import ArrayLike, NDArray
from phonopy.phonon.degeneracy import degenerate_sets
from phonopy.units import EV, Hbar, THz
from phonopy.physical_units import get_physical_units
from phono3py.file_IO import (
write_gamma_detail_to_hdf5,
@ -97,7 +100,11 @@ class ImagSelfEnergy:
# Unit to THz of Gamma
self._unit_conversion = (
18 * np.pi / (Hbar * EV) ** 2 / (2 * np.pi * THz) ** 2 * EV**2
18
* np.pi
/ (get_physical_units().Hbar * get_physical_units().EV) ** 2
/ (2 * np.pi * get_physical_units().THz) ** 2
* get_physical_units().EV ** 2
)
def run(self):
@ -288,7 +295,7 @@ class ImagSelfEnergy:
self._temperature = float(temperature)
def set_temperature(self, temperature):
"""Set temperatures where calculation will be peformed."""
"""Set temperature where calculation will be performed."""
warnings.warn(
"Use attribute, ImagSelfEnergy.temperature "
"instead of ImagSelfEnergy.set_temperature().",
@ -387,7 +394,7 @@ class ImagSelfEnergy:
self._triplets_at_q,
self._weights_at_q,
self._frequencies,
self._temperature,
self._temperature * get_physical_units().KB / get_physical_units().THzToEv,
self._g,
_g_zero,
self._cutoff_frequency,
@ -412,7 +419,7 @@ class ImagSelfEnergy:
self._weights_at_q,
self._pp.bz_grid.addresses,
self._frequencies,
self._temperature,
self._temperature * get_physical_units().KB / get_physical_units().THzToEv,
self._g,
_g_zero,
self._cutoff_frequency,
@ -436,7 +443,9 @@ class ImagSelfEnergy:
self._triplets_at_q,
self._weights_at_q,
self._frequencies,
self._temperature,
self._temperature
* get_physical_units().KB
/ get_physical_units().THzToEv,
self._g,
self._g_zero,
self._cutoff_frequency,
@ -471,7 +480,9 @@ class ImagSelfEnergy:
self._weights_at_q,
self._pp.bz_grid.addresses,
self._frequencies,
self._temperature,
self._temperature
* get_physical_units().KB
/ get_physical_units().THzToEv,
g,
_g_zero,
self._cutoff_frequency,
@ -568,20 +579,20 @@ class ImagSelfEnergy:
def get_imag_self_energy(
interaction: Interaction,
grid_points,
temperatures,
sigmas=None,
frequency_points=None,
frequency_step=None,
num_frequency_points=None,
frequency_points_at_bands=False,
num_points_in_batch=None,
scattering_event_class=None, # class 1 or 2
write_gamma_detail=False,
return_gamma_detail=False,
output_filename=None,
log_level=0,
):
grid_points: ArrayLike,
temperatures: ArrayLike,
sigmas: Sequence[float | None] | None = None,
frequency_points: ArrayLike | None = None,
frequency_step: float | None = None,
num_frequency_points: int | None = None,
frequency_points_at_bands: bool = False,
num_points_in_batch: int | None = None,
scattering_event_class: int | None = None, # class 1 or 2
write_gamma_detail: bool = False,
return_gamma_detail: bool = False,
output_filename: str | None = None,
log_level: int = 0,
) -> tuple[NDArray | None, NDArray, Sequence]:
"""Imaginary-part of self-energy at frequency points.
Band indices to be calculated at are found in Interaction instance.
@ -591,12 +602,12 @@ def get_imag_self_energy(
interaction : Interaction
Ph-ph interaction.
grid_points : array_like
Grid-point indices where imag-self-energeis are caclculated.
Grid-point indices where imag-self-energies are calculated.
dtype=int, shape=(grid_points,)
temperatures : array_like
Temperatures where imag-self-energies are calculated.
dtype=float, shape=(temperatures,)
sigmas : array_like, optional
sigmas : Sequence, optional
A set of sigmas. simgas=[None, ] means to use tetrahedron method,
otherwise smearing method with real positive value of sigma.
For example, sigmas=[None, 0.01, 0.03] is possible. Default is None,
@ -663,9 +674,7 @@ def get_imag_self_energy(
"""
if sigmas is None:
_sigmas = [
None,
]
_sigmas = [None]
else:
_sigmas = sigmas
@ -710,7 +719,7 @@ def get_imag_self_energy(
order="C",
)
detailed_gamma: List[Optional[np.ndarray]] = []
detailed_gamma = []
ise = ImagSelfEnergy(
interaction, with_detail=(write_gamma_detail or return_gamma_detail)
@ -763,10 +772,7 @@ def get_imag_self_energy(
log_level,
)
if return_gamma_detail:
return _frequency_points, gamma, detailed_gamma
else:
return _frequency_points, gamma
return _frequency_points, gamma, detailed_gamma
def _get_imag_self_energy_at_gp(
@ -1052,7 +1058,7 @@ def run_ise_at_frequency_points_batch(
if log_level:
print(
"Calculations at %d frequency points are devided into "
"Calculations at %d frequency points are divided into "
"%d batches." % (len(_frequency_points), len(batches))
)

View File

@ -35,15 +35,15 @@
# POSSIBILITY OF SUCH DAMAGE.
from __future__ import annotations
import warnings
from collections.abc import Sequence
from typing import Literal, Optional, Union
from typing import Literal
import numpy as np
from numpy.typing import NDArray
from phonopy.harmonic.dynamical_matrix import DynamicalMatrix, get_dynamical_matrix
from phonopy.physical_units import get_physical_units
from phonopy.structure.cells import Primitive, compute_all_sg_permutations
from phonopy.structure.symmetry import Symmetry
from phonopy.units import AMU, EV, Angstrom, Hbar, THz, VaspToTHz
from phono3py.phonon.grid import (
BZGrid,
@ -94,46 +94,49 @@ class Interaction:
primitive: Primitive,
bz_grid: BZGrid,
primitive_symmetry: Symmetry,
fc3: Optional[np.ndarray] = None,
band_indices: Optional[Union[np.ndarray, Sequence]] = None,
constant_averaged_interaction: Optional[float] = None,
frequency_factor_to_THz: float = VaspToTHz,
frequency_scale_factor: Optional[float] = None,
unit_conversion: Optional[float] = None,
fc3: NDArray | None = None,
fc3_nonzero_indices: NDArray | None = None,
band_indices: NDArray | Sequence | None = None,
constant_averaged_interaction: float | None = None,
frequency_factor_to_THz: float | None = None,
frequency_scale_factor: float | None = None,
unit_conversion: float | None = None,
is_mesh_symmetry: bool = True,
symmetrize_fc3q: bool = False,
make_r0_average: bool = False,
cutoff_frequency: Optional[float] = None,
cutoff_frequency: float | None = None,
lapack_zheev_uplo: Literal["L", "U"] = "L",
openmp_per_triplets: Optional[bool] = None,
openmp_per_triplets: bool | None = None,
):
"""Init method."""
self._primitive = primitive
self._bz_grid = bz_grid
self._primitive_symmetry = primitive_symmetry
self._band_indices = None
self._set_band_indices(band_indices)
self._band_indices = self._get_band_indices(band_indices)
self._constant_averaged_interaction = constant_averaged_interaction
self._frequency_factor_to_THz = frequency_factor_to_THz
if frequency_factor_to_THz is None:
self._frequency_factor_to_THz = get_physical_units().DefaultToTHz
else:
self._frequency_factor_to_THz = frequency_factor_to_THz
self._frequency_scale_factor = frequency_scale_factor
if fc3 is not None:
self._set_fc3(fc3)
self._set_fc3(fc3, fc3_nonzero_indices=fc3_nonzero_indices)
# Unit to eV^2
if unit_conversion is None:
num_grid = np.prod(self.mesh_numbers)
self._unit_conversion = (
(Hbar * EV) ** 3
self._unit_conversion = float(
(get_physical_units().Hbar * get_physical_units().EV) ** 3
/ 36
/ 8
* EV**2
/ Angstrom**6
/ (2 * np.pi * THz) ** 3
/ AMU**3
* get_physical_units().EV ** 2
/ get_physical_units().Angstrom ** 6
/ (2 * np.pi * get_physical_units().THz) ** 3
/ get_physical_units().AMU ** 3
/ num_grid
/ EV**2
/ get_physical_units().EV ** 2
)
else:
self._unit_conversion = unit_conversion
@ -144,7 +147,7 @@ class Interaction:
self._is_mesh_symmetry = is_mesh_symmetry
self._symmetrize_fc3q = symmetrize_fc3q
self._make_r0_average = make_r0_average
self._lapack_zheev_uplo = lapack_zheev_uplo
self._lapack_zheev_uplo: Literal["L", "U"] = lapack_zheev_uplo
self._openmp_per_triplets = openmp_per_triplets
self._symprec = self._primitive_symmetry.tolerance
@ -157,7 +160,8 @@ class Interaction:
self._g_zero = None
self._phonon_done = None
self._done_nac_at_gamma = False # Phonon at Gamma is calculatd with NAC.
self._phonon_all_done = False
self._done_nac_at_gamma = False # Phonon at Gamma is calculated with NAC.
self._frequencies = None
self._eigenvectors = None
self._frequencies_at_gamma = None
@ -178,13 +182,14 @@ class Interaction:
)
self._get_all_shortest()
def run(
self, lang: Literal["C", "Python"] = "C", g_zero: Optional[np.ndarray] = None
):
def run(self, lang: Literal["C", "Python"] = "C", g_zero: NDArray | None = None):
"""Run ph-ph interaction calculation."""
if (self._phonon_done == 0).any():
if self._phonon_all_done:
self.run_phonon_solver()
if self._triplets_at_q is None:
raise RuntimeError("Set grid point first by set_grid_point().")
num_band = len(self._primitive) * 3
num_triplets = len(self._triplets_at_q)
@ -204,7 +209,7 @@ class Interaction:
)
@property
def interaction_strength(self) -> np.ndarray:
def interaction_strength(self) -> NDArray | None:
"""Return ph-ph interaction strength.
Returns
@ -216,18 +221,8 @@ class Interaction:
"""
return self._interaction_strength
def get_interaction_strength(self):
"""Return ph-ph interaction strength."""
warnings.warn(
"Use attribute, Interaction.interaction_strength "
"instead of Interaction.get_interaction_strength().",
DeprecationWarning,
stacklevel=2,
)
return self.interaction_strength
@property
def mesh_numbers(self) -> np.ndarray:
def mesh_numbers(self) -> NDArray:
"""Return mesh numbers.
Returns
@ -238,73 +233,56 @@ class Interaction:
"""
return self._bz_grid.D_diag
def get_mesh_numbers(self):
"""Return mesh numbers."""
warnings.warn(
"Use attribute, Interaction.mesh_numbers "
"instead of Interaction.get_mesh_numbers().",
DeprecationWarning,
stacklevel=2,
)
return self.mesh_numbers
@property
def is_mesh_symmetry(self) -> bool:
"""Whether symmetry of grid is utilized or not."""
return self._is_mesh_symmetry
@property
def fc3(self) -> np.ndarray:
def fc3(self) -> NDArray:
"""Return fc3."""
return self._fc3
def get_fc3(self):
"""Return fc3."""
warnings.warn(
"Use attribute, Interaction.fc3 instead of Interaction.get_fc3().",
DeprecationWarning,
stacklevel=2,
)
return self.fc3
@property
def fc3_nonzero_indices(self) -> NDArray:
"""Return fc3_nonzero_indices."""
return self._fc3_nonzero_indices
@property
def dynamical_matrix(self) -> Optional[DynamicalMatrix]:
def dynamical_matrix(self) -> DynamicalMatrix | None:
"""Return DynamicalMatrix class instance."""
return self._dm
def get_dynamical_matrix(self):
"""Return DynamicalMatrix class instance."""
warnings.warn(
"Use attribute, Interaction.dynamical_matrix "
"instead of Interaction.get_dynamical_matrix().",
DeprecationWarning,
stacklevel=2,
)
return self.dynamical_matrix
@property
def primitive(self) -> Primitive:
"""Return Primitive class instance."""
return self._primitive
def get_primitive(self):
"""Return Primitive class instance."""
warnings.warn(
"Use attribute, Interaction.primitive "
"instead of Interaction.get_primitive().",
DeprecationWarning,
stacklevel=2,
)
return self.primitive
@property
def primitive_symmetry(self) -> Symmetry:
"""Return Symmetry class instance of primitive cell."""
return self._primitive_symmetry
@property
def phonon_all_done(self) -> bool:
"""Return whether phonon calculation is done at all grid points.
True value is set in run_phonon_solver(). Even when False, it is
possible that all phonons are already calculated, but it is safer to
think some of phonons are not calculated yet. To be sure, check
(self._phonon_done == 0).any().
"""
return self._phonon_all_done
def get_triplets_at_q(
self,
) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
) -> tuple[
NDArray | None,
NDArray | None,
NDArray | None,
NDArray | None,
]:
"""Return grid point triplets information.
triplets_at_q is in BZ-grid.
@ -326,7 +304,7 @@ class Interaction:
return self._bz_grid
@property
def band_indices(self) -> np.ndarray:
def band_indices(self) -> NDArray:
"""Return band indices.
Returns
@ -337,23 +315,13 @@ class Interaction:
"""
return self._band_indices
def get_band_indices(self):
"""Return band indices."""
warnings.warn(
"Use attribute, Interaction.band_indices "
"instead of Interaction.get_band_indices().",
DeprecationWarning,
stacklevel=2,
)
return self.band_indices
@property
def nac_params(self) -> dict:
def nac_params(self) -> dict | None:
"""Return NAC params."""
return self._nac_params
@property
def nac_q_direction(self) -> Optional[np.ndarray]:
def nac_q_direction(self) -> NDArray | None:
"""Return q-direction used for NAC at q->0.
Direction of q-vector watching from Gamma point used for
@ -373,28 +341,8 @@ class Interaction:
else:
self._nac_q_direction = np.array(nac_q_direction, copy=True, dtype="double")
def get_nac_q_direction(self):
"""Return q-direction used for NAC at q->0."""
warnings.warn(
"Use attribute, Interaction.nac_q_direction "
"instead of Interaction.get_nac_q_direction().",
DeprecationWarning,
stacklevel=2,
)
return self.nac_q_direction
def set_nac_q_direction(self, nac_q_direction=None):
"""Set NAC q-point direction valid at q->0."""
warnings.warn(
"Use attribute, Interaction.nac_q_direction "
"instead of Interaction.set_nac_q_direction().",
DeprecationWarning,
stacklevel=2,
)
self.nac_q_direction = nac_q_direction
@property
def zero_value_positions(self) -> Optional[np.ndarray]:
def zero_value_positions(self) -> NDArray | None:
"""Return zero ph-ph interaction elements information.
Returns
@ -404,17 +352,9 @@ class Interaction:
"""
return self._g_zero
def get_zero_value_positions(self):
"""Return zero ph-ph interaction elements information."""
warnings.warn(
"Use attribute, Interaction.zero_value_positions "
"instead of Interaction.get_zero_value_positions().",
DeprecationWarning,
stacklevel=2,
)
return self.zero_value_positions
def get_phonons(self) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
def get_phonons(
self,
) -> tuple[NDArray | None, NDArray | None, NDArray | None]:
"""Return phonons on grid.
Returns
@ -428,7 +368,7 @@ class Interaction:
shape=(num_bz_grid, num_band, num_band),
dtype="c%d" % (np.dtype('double').itemsize * 2), order='C'
phonon_done : ndarray
1 if phonon at a grid point is calcualted, otherwise 0.
1 if phonon at a grid point is calculated, otherwise 0.
shape=(num_bz_grid, ), dtype='byte'
"""
@ -439,48 +379,18 @@ class Interaction:
"""Return phonon frequency conversion factor to THz."""
return self._frequency_factor_to_THz
def get_frequency_factor_to_THz(self):
"""Return phonon frequency conversion factor to THz."""
warnings.warn(
"Use attribute, Interaction.frequency_factor_to_THz ",
"instead of Interaction.get_frequency_factor_to_THz().",
DeprecationWarning,
stacklevel=2,
)
return self.frequency_factor_to_THz
@property
def lapack_zheev_uplo(self) -> Literal["L", "U"]:
"""Return U or L for lapack zheev solver."""
return self._lapack_zheev_uplo
def get_lapack_zheev_uplo(self):
"""Return U or L for lapack zheev solver."""
warnings.warn(
"Use attribute, Interaction.lapack_zheev_uplo "
"instead of Interaction.get_lapack_zheev_uplo().",
DeprecationWarning,
stacklevel=2,
)
return self.lapack_zheev_uplo
@property
def cutoff_frequency(self) -> float:
"""Return cutoff phonon frequency to judge imaginary phonon."""
return self._cutoff_frequency
def get_cutoff_frequency(self):
"""Return cutoff phonon frequency to judge imaginary phonon."""
warnings.warn(
"Use attribute, Interaction.cutoff_frequency "
"instead of Interaction.get_cutoff_frequency().",
DeprecationWarning,
stacklevel=2,
)
return self.cutoff_frequency
@property
def openmp_per_triplets(self) -> bool:
def openmp_per_triplets(self) -> bool | None:
"""Return whether OpenMP distribution over triplets or bands."""
return self._openmp_per_triplets
@ -502,7 +412,7 @@ class Interaction:
return self._make_r0_average
@property
def all_shortest(self) -> np.ndarray:
def all_shortest(self) -> NDArray:
"""Return boolean of make_r0_average.
This flag is used to activate averaging of fc3 transformation
@ -514,31 +424,27 @@ class Interaction:
return self._all_shortest
@property
def averaged_interaction(self) -> np.ndarray:
def averaged_interaction(self) -> NDArray:
"""Return sum over phonon triplets of interaction strength.
See Eq.(21) of PRB 91, 094306 (2015)
"""
if self._interaction_strength is None or self._weights_at_q is None:
raise RuntimeError(
"Interaction strength and weights at q are not set. "
"Run Interaction.run() first."
)
# v[triplet, band0, band, band]
v = self._interaction_strength
w = self._weights_at_q
v_sum = np.dot(w, v.sum(axis=2).sum(axis=2))
return v_sum / np.prod(v.shape[2:])
def get_averaged_interaction(self):
"""Return sum over phonon triplets of interaction strength."""
warnings.warn(
"Use attribute, Interaction.averaged_interaction "
"instead of Interaction.get_averaged_interaction().",
DeprecationWarning,
stacklevel=2,
)
return self.averaged_interaction
def get_primitive_and_supercell_correspondence(
self,
) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
) -> tuple[NDArray, NDArray, NDArray, NDArray, NDArray]:
"""Return atomic pair information."""
return (self._svecs, self._multi, self._p2s, self._s2p, self._masses)
@ -547,31 +453,11 @@ class Interaction:
"""Return unit conversion factor."""
return self._unit_conversion
def get_unit_conversion_factor(self):
"""Return unit conversion factor."""
warnings.warn(
"Use attribute, Interaction.unit_conversion_factor "
"instead of Interaction.get_unit_conversion_factor().",
DeprecationWarning,
stacklevel=2,
)
return self.unit_conversion_factor
@property
def constant_averaged_interaction(self) -> float:
def constant_averaged_interaction(self) -> float | None:
"""Return constant averaged interaction."""
return self._constant_averaged_interaction
def get_constant_averaged_interaction(self):
"""Return constant averaged interaction."""
warnings.warn(
"Use attribute, Interaction.constant_averaged_interaction "
"instead of Interaction.get_constant_averaged_interaction().",
DeprecationWarning,
stacklevel=2,
)
return self.constant_averaged_interaction
def set_interaction_strength(self, pp_strength, g_zero=None):
"""Set interaction strength."""
self._interaction_strength = pp_strength
@ -626,7 +512,7 @@ class Interaction:
self.run_phonon_solver_at_gamma()
else:
msg = (
"Phonons at Gamma has been calcualted with NAC, "
"Phonons at Gamma has been calculated with NAC, "
"but ph-ph interaction is expected to calculate at "
"non-Gamma point. Setting Interaction.nac_q_direction = "
"None, can avoid raising this exception to re-run phonon "
@ -693,14 +579,22 @@ class Interaction:
"""Set phonons on grid."""
if bz_grid_addresses.shape != self._bz_grid.addresses.shape:
raise RuntimeError(
"Input grid address size is inconsistent. Setting phonons faild."
"Input grid address size is inconsistent. Setting phonons failed."
)
if (self._bz_grid.addresses - bz_grid_addresses).all():
raise RuntimeError(
"Input grid addresses are inconsistent. Setting phonons faild."
"Input grid addresses are inconsistent. Setting phonons failed."
)
else:
if (
self._phonon_done is None
or self._frequencies is None
or self._eigenvectors is None
):
raise RuntimeError(
"Phonons are not initialized. Call init_dynamical_matrix() first."
)
self._phonon_done[:] = 1
self._frequencies[:] = frequencies
self._eigenvectors[:] = eigenvectors
@ -717,6 +611,7 @@ class Interaction:
self._run_phonon_solver_c(
np.arange(len(self._bz_grid.addresses), dtype="int64")
)
self._phonon_all_done = True
else:
self._run_phonon_solver_c(grid_points)
@ -734,6 +629,15 @@ class Interaction:
otherwise without NAC. Default is False.
"""
if (
self._phonon_done is None
or self._frequencies is None
or self._eigenvectors is None
):
raise RuntimeError(
"Phonons are not initialized. Call init_dynamical_matrix() first."
)
if not is_nac and self._frequencies_at_gamma is not None:
gp_Gamma = self._bz_grid.gp_Gamma
self._frequencies[gp_Gamma] = self._frequencies_at_gamma
@ -762,6 +666,11 @@ class Interaction:
self._phonon_done
"""
if self._phonon_done is None:
raise RuntimeError(
"Phonons are not initialized. Call init_dynamical_matrix() first."
)
self._phonon_done[:] = 0
ir_grid_points, _, _ = get_ir_grid_points(self._bz_grid)
ir_bz_grid_points = self._bz_grid.grg2bzg[ir_grid_points]
@ -772,8 +681,8 @@ class Interaction:
# perms.shape = (len(spg_ops), len(primitive)), dtype='intc'
perms = compute_all_sg_permutations(
self._primitive.scaled_positions,
self._bz_grid.symmetry_dataset.rotations,
self._bz_grid.symmetry_dataset.translations,
self._bz_grid.symmetry_dataset.rotations, # type: ignore
self._bz_grid.symmetry_dataset.translations, # type: ignore
np.array(self._primitive.cell.T, dtype="double", order="C"),
symprec=self._symprec,
)
@ -821,13 +730,13 @@ class Interaction:
"""
d2r_map = []
for r in self._bz_grid.symmetry_dataset.rotations:
for r in self._bz_grid.symmetry_dataset.rotations: # type: ignore
for i, rec_r in enumerate(self._bz_grid.reciprocal_operations):
if (rec_r.T == r).all():
d2r_map.append(i)
break
assert len(d2r_map) == len(self._bz_grid.symmetry_dataset.rotations)
assert len(d2r_map) == len(self._bz_grid.symmetry_dataset.rotations) # type: ignore
return d2r_map
@ -837,8 +746,12 @@ class Interaction:
e_j'(Rq) = R e_j(q) exp(-iRq.\tau)
"""
assert self._phonon_done is not None
assert self._frequencies is not None
assert self._eigenvectors is not None
Rq = np.dot(self._bz_grid.QDinv, self._bz_grid.addresses[bzgp])
tau = self._bz_grid.symmetry_dataset.translations[t_i]
tau = self._bz_grid.symmetry_dataset.translations[t_i] # type: ignore
phase_factor = np.exp(-2j * np.pi * np.dot(Rq, tau))
self._phonon_done[bzgp] = 1
self._frequencies[bzgp, :] = self._frequencies[orig_gp, :]
@ -860,6 +773,10 @@ class Interaction:
in this method.
"""
assert self._phonon_done is not None
assert self._frequencies is not None
assert self._eigenvectors is not None
r_inv = -np.eye(3, dtype="int64")
bz_grid_points_solved = []
for bzgp, done in enumerate(self._phonon_done):
@ -905,7 +822,7 @@ class Interaction:
self._interaction_strength = None
self._g_zero = None
def _set_fc3(self, fc3):
def _set_fc3(self, fc3: NDArray, fc3_nonzero_indices: NDArray | None = None):
if (
isinstance(fc3, np.ndarray)
and fc3.dtype == np.dtype("double")
@ -922,20 +839,42 @@ class Interaction:
fc3 * self._frequency_scale_factor**2, dtype="double", order="C"
)
def _set_band_indices(self, band_indices):
if fc3_nonzero_indices is None:
self._fc3_nonzero_indices = np.ones(
self._fc3.shape[:3], dtype="byte", order="C"
)
elif (
isinstance(fc3_nonzero_indices, np.ndarray)
and fc3_nonzero_indices.dtype == np.dtype("byte")
and fc3_nonzero_indices.flags.aligned
and fc3_nonzero_indices.flags.owndata
and fc3_nonzero_indices.flags.c_contiguous
):
self._fc3_nonzero_indices = fc3_nonzero_indices
else:
self._fc3_nonzero_indices = np.array(
fc3_nonzero_indices, dtype="byte", order="C"
)
def _get_band_indices(self, band_indices) -> NDArray:
num_band = len(self._primitive) * 3
if band_indices is None:
self._band_indices = np.arange(num_band, dtype="int64")
return np.arange(num_band, dtype="int64")
else:
self._band_indices = np.array(band_indices, dtype="int64")
return np.array(band_indices, dtype="int64")
def _run_c(self, g_zero):
import phono3py._phono3py as phono3c
assert self._interaction_strength is not None
assert self._triplets_at_q is not None
num_band = len(self._primitive) * 3
if g_zero is None or self._symmetrize_fc3q:
_g_zero = np.zeros(
self._interaction_strength.shape, dtype="byte", order="C"
self._interaction_strength.shape,
dtype="byte",
order="C",
)
else:
_g_zero = g_zero
@ -960,6 +899,7 @@ class Interaction:
self._bz_grid.D_diag,
self._bz_grid.Q,
self._fc3,
self._fc3_nonzero_indices,
self._svecs,
self._multi,
self._masses,
@ -990,6 +930,11 @@ class Interaction:
)
def _run_py(self):
assert self._interaction_strength is not None
assert self._triplets_at_q is not None
assert self._frequencies is not None
assert self._eigenvectors is not None
r2r = RealToReciprocal(
self._fc3, self._primitive, self.mesh_numbers, symprec=self._symprec
)
@ -1008,8 +953,10 @@ class Interaction:
for gp in grid_triplet:
self._run_phonon_solver_py(gp)
r2n.run(fc3_reciprocal, grid_triplet)
fc3_normal = r2n.get_reciprocal_to_normal()
assert fc3_normal is not None
self._interaction_strength[i] = (
np.abs(r2n.get_reciprocal_to_normal()) ** 2 * self._unit_conversion
np.abs(fc3_normal) ** 2 * self._unit_conversion
)
def _run_phonon_solver_py(self, grid_point):
@ -1035,6 +982,7 @@ class Interaction:
num_band = len(self._primitive) * 3
num_grid = len(self._bz_grid.addresses)
self._phonon_done = np.zeros(num_grid, dtype="byte")
self._phonon_all_done = False
self._frequencies = np.zeros((num_grid, num_band), dtype="double", order="C")
complex_dtype = "c%d" % (np.dtype("double").itemsize * 2)
self._eigenvectors = np.zeros(

View File

@ -39,8 +39,8 @@ import warnings
import numpy as np
from phonopy.harmonic.dynamical_matrix import DynamicalMatrix, get_dynamical_matrix
from phonopy.physical_units import get_physical_units
from phonopy.structure.cells import Primitive, Supercell
from phonopy.units import VaspToTHz
from phono3py.phonon.func import bose_einstein
from phono3py.phonon.grid import BZGrid, get_grid_point_from_address
@ -66,7 +66,7 @@ class JointDos:
sigma=None,
sigma_cutoff=None,
cutoff_frequency=None,
frequency_factor_to_THz=VaspToTHz,
frequency_factor_to_THz=None,
frequency_scale_factor=1.0,
is_mesh_symmetry=True,
symprec=1e-5,
@ -90,7 +90,10 @@ class JointDos:
self._cutoff_frequency = 0
else:
self._cutoff_frequency = cutoff_frequency
self._frequency_factor_to_THz = frequency_factor_to_THz
if frequency_factor_to_THz is None:
self._frequency_factor_to_THz = get_physical_units().DefaultToTHz
else:
self._frequency_factor_to_THz = frequency_factor_to_THz
self._frequency_scale_factor = frequency_scale_factor
self._is_mesh_symmetry = is_mesh_symmetry
self._symprec = symprec
@ -103,7 +106,7 @@ class JointDos:
self._tetrahedron_method = None
self._phonon_done = None
self._done_nac_at_gamma = False # Phonon at Gamma is calculatd with NAC.
self._done_nac_at_gamma = False # Phonon at Gamma is calculated with NAC.
self._frequencies = None
self._eigenvectors = None
@ -255,7 +258,7 @@ class JointDos:
self._phonon_done[gamma_gp] = 0
else:
msg = (
"Phonons at Gamma has been calcualted with NAC, "
"Phonons at Gamma has been calculated with NAC, "
"but ph-ph interaction is expected to calculate at "
"non-Gamma point. Setting Interaction.nac_q_direction = "
"None, can avoid raising this exception to re-run phonon "
@ -388,7 +391,9 @@ class JointDos:
self._triplets_at_q,
self._weights_at_q,
self._frequencies,
self._temperature,
self._temperature
* get_physical_units().KB
/ get_physical_units().THzToEv,
g,
self._g_zero,
self._cutoff_frequency,

View File

@ -38,7 +38,7 @@ import sys
import numpy as np
from phonopy.phonon.degeneracy import degenerate_sets
from phonopy.units import EV, Hbar, THz
from phonopy.physical_units import get_physical_units
from phono3py.file_IO import (
write_real_self_energy_at_grid_point,
@ -63,9 +63,9 @@ class RealSelfEnergy:
How to test epsilon
-------------------
At a sampling mesh, choose one band and calcualte frequency shifts at
various epsilon values and plot over the epsilons. Decreasing epsinon,
at some point, discontinous change may be found.
At a sampling mesh, choose one band and calculate frequency shifts at
various epsilon values and plot over the epsilons. Decreasing epsilon,
at some point, discontinuous change may be found.
"""
@ -115,7 +115,12 @@ class RealSelfEnergy:
self._real_self_energies = None
# Unit to THz of Delta
self._unit_conversion = 18 / (Hbar * EV) ** 2 / (2 * np.pi * THz) ** 2 * EV**2
self._unit_conversion = (
18
/ (get_physical_units().Hbar * get_physical_units().EV) ** 2
/ (2 * np.pi * get_physical_units().THz) ** 2
* get_physical_units().EV ** 2
)
def run(self):
"""Calculate real-part of self-energies."""
@ -240,7 +245,7 @@ class RealSelfEnergy:
self._weights_at_q,
self._frequencies,
self._band_indices,
self._temperature,
self._temperature * get_physical_units().KB / get_physical_units().THzToEv,
self._epsilon,
self._unit_conversion,
self._cutoff_frequency,
@ -277,7 +282,9 @@ class RealSelfEnergy:
self._weights_at_q,
self._frequencies,
self._band_indices,
self._temperature,
self._temperature
* get_physical_units().KB
/ get_physical_units().THzToEv,
self._epsilon,
self._unit_conversion,
self._cutoff_frequency,

Some files were not shown because too many files have changed in this diff Show More