├── .github └── workflows │ ├── package.yml │ └── test.yml ├── .gitignore ├── .zenodo.json ├── LICENSE ├── README.md ├── img ├── color.png ├── convert.sh ├── cover.png └── cover.svg ├── pyproject.toml ├── requirements.txt ├── tests └── test.py └── xcauto ├── __init__.py ├── derv.py └── functionals ├── __init__.py ├── becke.py ├── lyp.py ├── pbe.py ├── slater.py ├── utils.py └── vwn.py /.github/workflows/package.yml: -------------------------------------------------------------------------------- 1 | name: Package 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: ${{ matrix.os }} 11 | strategy: 12 | matrix: 13 | python-version: [3.6] 14 | os: [ubuntu-latest] 15 | 16 | steps: 17 | - name: Switch branch 18 | uses: actions/checkout@v2 19 | - name: Set up Python ${{ matrix.python-version }} 20 | uses: actions/setup-python@v1 21 | with: 22 | python-version: ${{ matrix.python-version }} 23 | - name: Install Python dependencies 24 | run: | 25 | which python 26 | python -m pip install --upgrade pip 27 | pip install -r requirements.txt 28 | - name: Flit publish 29 | run: 30 | flit publish 31 | env: 32 | FLIT_USERNAME: __token__ 33 | FLIT_PASSWORD: ${{ secrets.PYPI_TOKEN }} 34 | # FLIT_INDEX_URL: https://test.pypi.org/legacy/ 35 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ${{ matrix.os }} 13 | strategy: 14 | matrix: 15 | python-version: [3.6, 3.7, 3.8] 16 | os: [ubuntu-latest, macOS-latest] 17 | 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v2 21 | - name: Set up Python ${{ matrix.python-version }} 22 | uses: actions/setup-python@v1 23 | with: 24 | python-version: ${{ matrix.python-version }} 25 | - name: Install Python dependencies 26 | run: | 27 | pip install -r requirements.txt 28 | flit install --symlink 29 | - name: Run tests 30 | run: | 31 | pytest -sv tests/test.py 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | venv/ 3 | -------------------------------------------------------------------------------- /.zenodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "creators": [ 3 | { 4 | "name": "Bast, Radovan" 5 | }, 6 | { 7 | "name": "Di Remigio, Roberto" 8 | }, 9 | { 10 | "name": "Ekström, Ulf" 11 | } 12 | ], 13 | "license": { 14 | "id": "MPL-2.0" 15 | }, 16 | "title": "xcauto: Arbitrary order exchange-correlation functional derivatives using JAX" 17 | } 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build status](https://github.com/dftlibs/xcauto/workflows/Test/badge.svg)](https://github.com/dftlibs/xcauto/actions) 2 | [![PyPI badge](https://badge.fury.io/py/xcauto.svg)](https://badge.fury.io/py/xcauto) 3 | [![License](https://img.shields.io/badge/license-%20MPL--v2.0-blue.svg)](LICENSE) 4 | [![DOI](https://zenodo.org/badge/277583759.svg)](https://zenodo.org/badge/latestdoi/277583759) 5 | 6 | 7 | # xcauto 8 | 9 | Arbitrary order exchange-correlation functional derivatives using 10 | [JAX](https://jax.readthedocs.io/) 11 | 12 | ![Automatic for the functions, easy for the people](img/cover.png) 13 | 14 | This library computes arbitrary-order exchange-correlation function(al) derivatives 15 | using [JAX](https://jax.readthedocs.io/). 16 | 17 | The emphasis of this project is on **ease of use** and **ease of adding 18 | functionals** in **Python**. The focus is not (yet) on performance. Our hope is 19 | that this project can make it easier to test new implementations of functional 20 | derivatives but maybe also used directly to provide functional derivatives in a 21 | density functional theory program. 22 | 23 | The code is in proof of concept stage. We have [ideas for more](#ideas). 24 | 25 | 26 | ## Acknowledgements and recommended citation 27 | 28 | [JAX](https://jax.readthedocs.io/) does all the heavy lifting by 29 | automatically differentiating the exchange-correlation functions. Please 30 | acknowledge their authors when using this code: 31 | https://github.com/google/jax#citing-jax: 32 | 33 | ``` 34 | @software{jax2018github, 35 | author = {James Bradbury and Roy Frostig and Peter Hawkins and Matthew James Johnson and Chris Leary and Dougal Maclaurin and Skye Wanderman-Milne}, 36 | title = {{JAX}: composable transformations of {P}ython+{N}um{P}y programs}, 37 | url = {http://github.com/google/jax}, 38 | version = {0.1.55}, 39 | year = {2018}, 40 | } 41 | ``` 42 | 43 | - We have used [Libxc](https://www.tddft.org/programs/libxc/) as reference to 44 | double check the computed derivatives. 45 | - The functional definitions for VWN and PBE were ported to Python based on the 46 | functional definitions found in [XCFun](https://github.com/dftlibs/xcfun) 47 | (Copyright Ulf Ekström and contributors, Mozilla Public License v2.0). 48 | 49 | 50 | ## Authors 51 | 52 | - Radovan Bast 53 | - Roberto Di Remigio 54 | - Ulf Ekström 55 | 56 | 57 | ## Installation 58 | 59 | You can install this code from PyPI: 60 | ``` 61 | $ pip install xcauto 62 | ``` 63 | 64 | Installing a development version: 65 | ``` 66 | $ git clone https://github.com/dftlibs/xcauto 67 | $ cd xcauto 68 | $ python -m venv venv 69 | $ source venv/bin/activate 70 | $ pip install -r requirements.txt 71 | $ flit install --symlink 72 | ``` 73 | 74 | ### Using on the Hylleraas Fleet 75 | 76 | The machines in the Fleet are properly set up to run JAX on their GPUs. The instructions to install `xcauto` are slightly modified, since we'll need a GPU-aware version of [JAX](https://jax.readthedocs.io/): 77 | ``` 78 | $ git clone https://github.com/dftlibs/xcauto 79 | $ cd xcauto 80 | $ python -m venv venv 81 | $ source venv/bin/activate 82 | $ pip install -r requirements.txt 83 | $ pip install --upgrade https://storage.googleapis.com/jax-releases/`nvidia-smi | sed -En "s/.* CUDA Version: ([0-9]*)\.([0-9]*).*/cuda\1\2/p"`/jaxlib-0.1.51-`python3 -V | sed -En "s/Python ([0-9]*)\.([0-9]*).*/cp\1\2/p"`-none-manylinux2010_x86_64.whl jax 84 | $ flit install --symlink 85 | ``` 86 | 87 | To run: 88 | ``` 89 | $ env XLA_FLAGS=--xla_gpu_cuda_data_dir=/lib/cuda python -m pytest tests/test.py 90 | ``` 91 | The environment variable **is important**: JAX won't be able to use the GPU otherwise. 92 | 93 | 94 | ## Example 95 | 96 | In this example we only go up to first-order derivatives 97 | but no problem to ask for higher-order derivatives (mixed or not). 98 | 99 | First `pip install xcauto`, then: 100 | 101 | ```python 102 | # use double precision floats 103 | from jax.config import config 104 | config.update("jax_enable_x64", True) 105 | 106 | from xcauto.functionals import pbex_n_gnn, pbec_n_gnn, pbec_a_b_gaa_gab_gbb 107 | from xcauto.derv import derv 108 | 109 | 110 | def pbe_unpolarized(n, gnn): 111 | return pbex_n_gnn(n, gnn) + pbec_n_gnn(n, gnn) 112 | 113 | 114 | print('up to first-order derivatives for spin-unpolarized pbe:') 115 | 116 | n = 0.02 117 | gnn = 0.05 118 | 119 | d_00 = derv(pbe_unpolarized, [n, gnn], [0, 0]) 120 | d_10 = derv(pbe_unpolarized, [n, gnn], [1, 0]) 121 | d_01 = derv(pbe_unpolarized, [n, gnn], [0, 1]) 122 | 123 | print(d_00) # -0.006987994564372291 124 | print(d_10) # -0.43578312569769495 125 | print(d_01) # -0.004509994863217848 126 | 127 | 128 | print('few derivatives for spin-polarized pbec:') 129 | 130 | fun = pbec_a_b_gaa_gab_gbb 131 | a = 0.02 132 | b = 0.05 133 | gaa = 0.02 134 | gab = 0.03 135 | gbb = 0.04 136 | 137 | d_00000 = derv(fun, [a, b, gaa, gab, gbb], [0, 0, 0, 0, 0]) 138 | d_10000 = derv(fun, [a, b, gaa, gab, gbb], [1, 0, 0, 0, 0]) 139 | d_01000 = derv(fun, [a, b, gaa, gab, gbb], [0, 1, 0, 0, 0]) 140 | d_00100 = derv(fun, [a, b, gaa, gab, gbb], [0, 0, 1, 0, 0]) 141 | d_00010 = derv(fun, [a, b, gaa, gab, gbb], [0, 0, 0, 1, 0]) 142 | d_00001 = derv(fun, [a, b, gaa, gab, gbb], [0, 0, 0, 0, 1]) 143 | 144 | print(d_00000) # -0.0002365056872298918 145 | print(d_10000) # -0.020444840022142356 146 | print(d_01000) # -0.015836702168478496 147 | print(d_00100) # 0.0030212897704793786 148 | print(d_00010) # 0.006042579540958757 149 | print(d_00001) # 0.0030212897704793786 150 | ``` 151 | 152 | For more examples, see the [tests folder](tests). 153 | 154 | 155 | ## Functionals 156 | 157 | List of implemented functions: 158 | ``` 159 | slaterx_n 160 | slaterx_a_b 161 | vwn3_n 162 | vwn3_a_b 163 | vwn5_n 164 | vwn5_a_b 165 | pbex_n_gnn 166 | pbex_a_b_gaa_gbb 167 | pbec_n_gnn 168 | pbec_a_b_gaa_gab_gbb 169 | b88_n_gnn 170 | b88_a_b_gaa_gbb 171 | lyp_n_gnn 172 | lyp_a_b_gaa_gab_gbb 173 | ``` 174 | 175 | **Where are all the other functionals?** We will be adding more but our hope is 176 | that the community will contribute these also. It is very little work to define 177 | a functional so please send pull requests! All the derivatives you get "for 178 | free" thanks to [JAX](https://jax.readthedocs.io/). 179 | 180 | 181 | ## Ideas 182 | 183 | Here we list few ideas that would be good to explore but which we haven't done 184 | yet: 185 | 186 | - Check performance 187 | - Try how the code offloads to GPU or TPU 188 | - Verify numerical stability for small densities 189 | - Adding more functionals 190 | - Directional derivatives 191 | - Contracting derivatives with perturbed densities 192 | -------------------------------------------------------------------------------- /img/color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dftlibs/xcauto/ab853a7ed4963b2522d4e01d8defbc661daea126/img/color.png -------------------------------------------------------------------------------- /img/convert.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | convert color.png -set colorspace Gray gray.png 4 | convert gray.png -gamma 0.3 gamma.png 5 | convert gamma.png -fill black -colorize 40% darker.png 6 | -------------------------------------------------------------------------------- /img/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dftlibs/xcauto/ab853a7ed4963b2522d4e01d8defbc661daea126/img/cover.png -------------------------------------------------------------------------------- /img/cover.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 55 | 62 | AUTOMATIC FOR THE FUNCTIONS 73 | 81 | X.C.AUTO 92 | EASY FOR THE PEOPLE 103 | 104 | 105 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["flit_core >=2,<4"] 3 | build-backend = "flit_core.buildapi" 4 | 5 | [tool.flit.metadata] 6 | module = "xcauto" 7 | author = "Radovan Bast" 8 | author-email = "radovan.bast@uit.no" 9 | home-page = "https://github.com/dftlibs/xcauto" 10 | requires=[ 11 | "jax", 12 | "jaxlib", 13 | ] 14 | description-file="README.md" 15 | classifiers = ["License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)"] 16 | 17 | [tool.flit.metadata.requires-extra] 18 | test = [ 19 | "pytest", 20 | ] 21 | dev = [ 22 | "black", 23 | ] 24 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | flit 2 | -------------------------------------------------------------------------------- /tests/test.py: -------------------------------------------------------------------------------- 1 | from jax.config import config 2 | 3 | config.update("jax_enable_x64", True) 4 | 5 | from xcauto.functionals import ( 6 | slaterx_n, 7 | slaterx_a_b, 8 | vwn3_n, 9 | vwn3_a_b, 10 | vwn5_n, 11 | vwn5_a_b, 12 | pbex_n_gnn, 13 | pbex_a_b_gaa_gbb, 14 | pbec_n_gnn, 15 | pbec_a_b_gaa_gab_gbb, 16 | b88_n_gnn, 17 | b88_a_b_gaa_gbb, 18 | lyp_n_gnn, 19 | lyp_a_b_gaa_gab_gbb, 20 | ) 21 | from xcauto.derv import derv 22 | 23 | import pytest 24 | 25 | 26 | def test_slaterx_unpolarized(): 27 | fun = slaterx_n 28 | n = 0.05 29 | 30 | d_0 = derv(fun, [n], [0]) 31 | d_1 = derv(fun, [n], [1]) 32 | 33 | assert d_0 == pytest.approx(-0.01360436879474179) 34 | assert d_1 == pytest.approx(-0.362783167859781) 35 | 36 | 37 | def test_slaterx_polarized(): 38 | fun = slaterx_a_b 39 | a = 0.02 40 | b = 0.05 41 | 42 | d_00 = derv(fun, [a, b], [0, 0]) 43 | d_10 = derv(fun, [a, b], [1, 0]) 44 | d_01 = derv(fun, [a, b], [0, 1]) 45 | 46 | assert d_00 == pytest.approx(-0.022192101517910012) 47 | assert d_10 == pytest.approx(-0.33677806019212597) 48 | assert d_01 == pytest.approx(-0.4570781497340833) 49 | 50 | 51 | def test_vwn3_unpolarized(): 52 | fun = vwn3_n 53 | n = 0.05 54 | 55 | d_0 = derv(fun, [n], [0]) 56 | d_1 = derv(fun, [n], [1]) 57 | 58 | assert d_0 == pytest.approx(-0.0033243334606879206) 59 | assert d_1 == pytest.approx(-0.07438806748231225) 60 | 61 | 62 | def test_vwn3_polarized(): 63 | fun = vwn3_a_b 64 | a = 0.02 65 | b = 0.05 66 | 67 | d_00 = derv(fun, [a, b], [0, 0]) 68 | d_10 = derv(fun, [a, b], [1, 0]) 69 | d_01 = derv(fun, [a, b], [0, 1]) 70 | 71 | assert d_00 == pytest.approx(-0.004585556701793601) 72 | assert d_10 == pytest.approx(-0.09784372868839261) 73 | assert d_01 == pytest.approx(-0.06303262897292465) 74 | 75 | 76 | def test_vwn5_unpolarized(): 77 | fun = vwn5_n 78 | n = 0.05 79 | 80 | d_0 = derv(fun, [n], [0]) 81 | d_1 = derv(fun, [n], [1]) 82 | 83 | assert d_0 == pytest.approx(-0.0024185694846377663) 84 | assert d_1 == pytest.approx(-0.05545437748839972) 85 | 86 | 87 | def test_vwn5_polarized(): 88 | fun = vwn5_a_b 89 | a = 0.02 90 | b = 0.05 91 | 92 | d_00 = derv(fun, [a, b], [0, 0]) 93 | d_10 = derv(fun, [a, b], [1, 0]) 94 | d_01 = derv(fun, [a, b], [0, 1]) 95 | 96 | assert d_00 == pytest.approx(-0.0033313701535310127) 97 | assert d_10 == pytest.approx(-0.07637590965268805) 98 | assert d_01 == pytest.approx(-0.04561294583487131) 99 | 100 | 101 | def test_pbex_unpolarized(): 102 | fun = pbex_n_gnn 103 | n = 0.05 104 | gnn = 0.05 105 | 106 | d_00 = derv(fun, [n, gnn], [0, 0]) 107 | d_10 = derv(fun, [n, gnn], [1, 0]) 108 | d_01 = derv(fun, [n, gnn], [0, 1]) 109 | 110 | assert d_00 == pytest.approx(-0.019209216943125326) 111 | assert d_10 == pytest.approx(-0.3664969949653799) 112 | assert d_01 == pytest.approx(-0.05465579631923576) 113 | 114 | 115 | def test_pbec_unpolarized(): 116 | fun = pbec_n_gnn 117 | n = 0.05 118 | gnn = 0.05 119 | 120 | d_00 = derv(fun, [n, gnn], [0, 0]) 121 | d_10 = derv(fun, [n, gnn], [1, 0]) 122 | d_01 = derv(fun, [n, gnn], [0, 1]) 123 | 124 | assert d_00 == pytest.approx(-0.0001881151998459174) 125 | assert d_10 == pytest.approx(-0.018915857103503467) 126 | assert d_01 == pytest.approx(0.005695886444674986) 127 | 128 | 129 | def test_pbex_polarized(): 130 | fun = pbex_a_b_gaa_gbb 131 | a = 0.02 132 | b = 0.05 133 | gaa = 0.02 134 | gbb = 0.04 135 | 136 | d_0000 = derv(fun, [a, b, gaa, gbb], [0, 0, 0, 0]) 137 | d_1000 = derv(fun, [a, b, gaa, gbb], [1, 0, 0, 0]) 138 | d_0100 = derv(fun, [a, b, gaa, gbb], [0, 1, 0, 0]) 139 | d_0010 = derv(fun, [a, b, gaa, gbb], [0, 0, 1, 0]) 140 | d_0001 = derv(fun, [a, b, gaa, gbb], [0, 0, 0, 1]) 141 | 142 | assert d_0000 == pytest.approx(-0.030022232676348133) 143 | assert d_1000 == pytest.approx(-0.4399544626404114) 144 | assert d_0100 == pytest.approx(-0.4179516165421625) 145 | assert d_0010 == pytest.approx(-0.037768955504833064) 146 | assert d_0001 == pytest.approx(-0.07798714870271929) 147 | 148 | 149 | def test_pbec_polarized(): 150 | fun = pbec_a_b_gaa_gab_gbb 151 | a = 0.02 152 | b = 0.05 153 | gaa = 0.02 154 | gab = 0.03 155 | gbb = 0.04 156 | 157 | d_00000 = derv(fun, [a, b, gaa, gab, gbb], [0, 0, 0, 0, 0]) 158 | d_10000 = derv(fun, [a, b, gaa, gab, gbb], [1, 0, 0, 0, 0]) 159 | d_01000 = derv(fun, [a, b, gaa, gab, gbb], [0, 1, 0, 0, 0]) 160 | d_00100 = derv(fun, [a, b, gaa, gab, gbb], [0, 0, 1, 0, 0]) 161 | d_00010 = derv(fun, [a, b, gaa, gab, gbb], [0, 0, 0, 1, 0]) 162 | d_00001 = derv(fun, [a, b, gaa, gab, gbb], [0, 0, 0, 0, 1]) 163 | 164 | assert d_00000 == pytest.approx(-0.0002365056872298918) 165 | assert d_10000 == pytest.approx(-0.020444840022142356) 166 | assert d_01000 == pytest.approx(-0.015836702168478496) 167 | assert d_00100 == pytest.approx(0.0030212897704793786) 168 | assert d_00010 == pytest.approx(0.006042579540958757) 169 | assert d_00001 == pytest.approx(0.0030212897704793786) 170 | 171 | 172 | def test_b88_unpolarized(): 173 | fun = b88_n_gnn 174 | n = 0.05 175 | gnn = 0.05 176 | 177 | d_00 = derv(fun, [n, gnn], [0, 0]) 178 | d_10 = derv(fun, [n, gnn], [1, 0]) 179 | d_01 = derv(fun, [n, gnn], [0, 1]) 180 | 181 | assert d_00 == pytest.approx(-0.01979886998407452) 182 | assert d_10 == pytest.approx(-0.3189432578863246) 183 | assert d_01 == pytest.approx(-0.07838497813337346) 184 | 185 | 186 | def test_b88_polarized(): 187 | fun = b88_a_b_gaa_gbb 188 | a = 0.02 189 | b = 0.05 190 | gaa = 0.02 191 | gbb = 0.04 192 | 193 | d_0000 = derv(fun, [a, b, gaa, gbb], [0, 0, 0, 0]) 194 | d_1000 = derv(fun, [a, b, gaa, gbb], [1, 0, 0, 0]) 195 | d_0100 = derv(fun, [a, b, gaa, gbb], [0, 1, 0, 0]) 196 | d_0010 = derv(fun, [a, b, gaa, gbb], [0, 0, 1, 0]) 197 | d_0001 = derv(fun, [a, b, gaa, gbb], [0, 0, 0, 1]) 198 | 199 | assert d_0000 == pytest.approx(-0.03144503226070762) 200 | assert d_1000 == pytest.approx(-0.3093251926971783) 201 | assert d_0100 == pytest.approx(-0.4049705102105752) 202 | assert d_0010 == pytest.approx(-0.11788498562531187) 203 | assert d_0001 == pytest.approx(-0.08629201015426126) 204 | 205 | 206 | def test_lyp_unpolarized(): 207 | fun = lyp_n_gnn 208 | n = 0.05 209 | gnn = 0.05 210 | 211 | d_00 = derv(fun, [n, gnn], [0, 0]) 212 | d_10 = derv(fun, [n, gnn], [1, 0]) 213 | d_01 = derv(fun, [n, gnn], [0, 1]) 214 | 215 | assert d_00 == pytest.approx(0.00042087780985987616) 216 | assert d_10 == pytest.approx(-0.09263104903773431) 217 | assert d_01 == pytest.approx(0.0384853034977648) 218 | 219 | 220 | def test_lyp_polarized(): 221 | fun = lyp_a_b_gaa_gab_gbb 222 | a = 0.02 223 | b = 0.05 224 | gaa = 0.02 225 | gab = 0.03 226 | gbb = 0.04 227 | 228 | d_00000 = derv(fun, [a, b, gaa, gab, gbb], [0, 0, 0, 0, 0]) 229 | d_10000 = derv(fun, [a, b, gaa, gab, gbb], [1, 0, 0, 0, 0]) 230 | d_01000 = derv(fun, [a, b, gaa, gab, gbb], [0, 1, 0, 0, 0]) 231 | d_00100 = derv(fun, [a, b, gaa, gab, gbb], [0, 0, 1, 0, 0]) 232 | d_00010 = derv(fun, [a, b, gaa, gab, gbb], [0, 0, 0, 1, 0]) 233 | d_00001 = derv(fun, [a, b, gaa, gab, gbb], [0, 0, 0, 0, 1]) 234 | 235 | assert d_00000 == pytest.approx(0.001542746435862988) 236 | assert d_10000 == pytest.approx(-0.24548979946312044) 237 | assert d_01000 == pytest.approx(-0.049365492793595686) 238 | assert d_00100 == pytest.approx(0.07934548180341987) 239 | assert d_00010 == pytest.approx(0.07002272860406972) 240 | assert d_00001 == pytest.approx(-0.004609128608335719) 241 | -------------------------------------------------------------------------------- /xcauto/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | xcauto: Arbitrary order exchange-correlation functional derivatives using JAX. 3 | """ 4 | 5 | __version__ = "0.2.0" 6 | -------------------------------------------------------------------------------- /xcauto/derv.py: -------------------------------------------------------------------------------- 1 | from jax import grad 2 | 3 | 4 | def _derv_sequence(orders): 5 | sequence = [] 6 | for variable, variable_order in enumerate(orders): 7 | if variable_order > 0: 8 | sequence += variable_order * [variable] 9 | return sequence 10 | 11 | 12 | def test_derv_sequence(): 13 | assert _derv_sequence((3, 2, 1, 0)) == [0, 0, 0, 1, 1, 2] 14 | assert _derv_sequence((0, 1, 2, 3)) == [1, 2, 2, 3, 3, 3] 15 | assert _derv_sequence((0, 1, 0, 1)) == [1, 3] 16 | 17 | 18 | def derv(fun, variables, orders) -> float: 19 | """ 20 | fun: function to differentiate which expects a certain number of variables 21 | variables: list of variables at which to differentiate the function 22 | orders: [1, 0, 2, 0] means differentate with respect to variable 1 once, 23 | and differentiate with respect to variable 3 twice. 24 | """ 25 | sequence = _derv_sequence(orders) 26 | functions = [fun] 27 | for i, order in enumerate(sequence): 28 | functions.append(grad(functions[i], (order))) 29 | return functions[-1](*variables) 30 | -------------------------------------------------------------------------------- /xcauto/functionals/__init__.py: -------------------------------------------------------------------------------- 1 | from .slater import slaterx_n, slaterx_a_b 2 | 3 | from .vwn import vwn3_n, vwn3_a_b, vwn5_n, vwn5_a_b 4 | 5 | from .pbe import pbex_n_gnn, pbex_a_b_gaa_gbb, pbec_n_gnn, pbec_a_b_gaa_gab_gbb 6 | 7 | from .becke import b88_n_gnn, b88_a_b_gaa_gbb 8 | 9 | from .lyp import lyp_n_gnn, lyp_a_b_gaa_gab_gbb 10 | -------------------------------------------------------------------------------- /xcauto/functionals/becke.py: -------------------------------------------------------------------------------- 1 | # The functional definition in this file was ported to Python 2 | # from XCFun, which is Copyright Ulf Ekström and contributors 2009-2020 3 | # and provided under the Mozilla Public License (v2.0) 4 | # see also: 5 | # - https://github.com/dftlibs/xcfun 6 | # - https://github.com/dftlibs/xcfun/blob/master/LICENSE.md 7 | 8 | 9 | import jax.numpy as np 10 | 11 | from .slater import slaterx_a 12 | 13 | 14 | def _b88_a_gaa(a, gaa): 15 | na43 = a ** (4.0 / 3.0) 16 | chi2 = gaa * a ** (-8.0 / 3.0) 17 | chi = np.sqrt(chi2) 18 | d = 0.0042 19 | b88 = -(d * na43 * chi2) / (1.0 + 6.0 * d * chi * np.arcsinh(chi)) 20 | return slaterx_a(a) + b88 21 | 22 | 23 | def b88_a_b_gaa_gbb(a, b, gaa, gbb): 24 | return _b88_a_gaa(a, gaa) + _b88_a_gaa(b, gbb) 25 | 26 | 27 | def b88_n_gnn(n, gnn): 28 | a = 0.5 * n 29 | b = 0.5 * n 30 | gaa = 0.25 * gnn 31 | gbb = gaa 32 | return b88_a_b_gaa_gbb(a, b, gaa, gbb) 33 | -------------------------------------------------------------------------------- /xcauto/functionals/lyp.py: -------------------------------------------------------------------------------- 1 | # The functional definition in this file was ported to Python 2 | # from XCFun, which is Copyright Ulf Ekström and contributors 2009-2020 3 | # and provided under the Mozilla Public License (v2.0) 4 | # see also: 5 | # - https://github.com/dftlibs/xcfun 6 | # - https://github.com/dftlibs/xcfun/blob/master/LICENSE.md 7 | 8 | 9 | import jax.numpy as np 10 | 11 | 12 | def lyp_a_b_gaa_gab_gbb(a, b, gaa, gab, gbb): 13 | 14 | A = 0.04918 15 | B = 0.132 16 | C = 0.2533 17 | Dd = 0.349 18 | 19 | n = a + b 20 | gnn = gaa + 2.0 * gab + gbb 21 | 22 | CF = 0.3 * (3.0 * np.pi * np.pi) ** (2.0 / 3.0) 23 | icbrtn = n ** (-1.0 / 3.0) 24 | P = 1.0 / (1.0 + Dd * icbrtn) 25 | omega = np.exp(-C * icbrtn) * P * n ** (-11.0 / 3.0) 26 | delta = icbrtn * (C + Dd * P) 27 | n2 = n * n 28 | return -A * ( 29 | 4.0 * a * b * P / n 30 | + B 31 | * omega 32 | * ( 33 | a 34 | * b 35 | * ( 36 | 2.0 ** (11.0 / 3.0) * CF * (a ** (8.0 / 3.0) + b ** (8.0 / 3.0)) 37 | + (47.0 - 7.0 * delta) * gnn / 18.0 38 | - (2.5 - delta / 18.0) * (gaa + gbb) 39 | - (delta - 11.0) / 9.0 * (a * gaa + b * gbb) / n 40 | ) 41 | - 2.0 / 3.0 * n2 * gnn 42 | + (2.0 / 3.0 * n2 - a * a) * gbb 43 | + (2.0 / 3.0 * n2 - b * b) * gaa 44 | ) 45 | ) 46 | 47 | 48 | def lyp_n_gnn(n, gnn): 49 | a = 0.5 * n 50 | b = 0.5 * n 51 | gaa = 0.25 * gnn 52 | gab = gaa 53 | gbb = gaa 54 | return lyp_a_b_gaa_gab_gbb(a, b, gaa, gab, gbb) 55 | -------------------------------------------------------------------------------- /xcauto/functionals/pbe.py: -------------------------------------------------------------------------------- 1 | # The functional definition in this file was ported to Python 2 | # from XCFun, which is Copyright Ulf Ekström and contributors 2009-2020 3 | # and provided under the Mozilla Public License (v2.0) 4 | # see also: 5 | # - https://github.com/dftlibs/xcfun 6 | # - https://github.com/dftlibs/xcfun/blob/master/LICENSE.md 7 | 8 | 9 | import jax.numpy as np 10 | 11 | from .utils import ufunc 12 | 13 | param_gamma = (1.0 - np.log(2.0)) / (np.pi * np.pi) 14 | # param_beta_pbe_paper = 0.066725 15 | param_beta_accurate = 0.06672455060314922 16 | param_beta_gamma = param_beta_accurate / param_gamma 17 | 18 | 19 | def _prefactor(a): 20 | return ( 21 | -0.75 22 | * 2.0 ** (1.0 / 3.0) 23 | * (3.0 * np.pi * np.pi) ** (1.0 / 3.0) 24 | * a ** (4.0 / 3.0) 25 | / np.pi 26 | ) 27 | 28 | 29 | def _enhancement(R, a, gaa): 30 | # some codes use this instead: 31 | # mu = 0.2195149727645171 32 | mu = 0.066725 * np.pi * np.pi / 3.0 33 | st2 = ( 34 | gaa 35 | / a ** (8.0 / 3.0) 36 | * (6.0 ** (2.0 / 3.0) / (12.0 * np.pi ** (2.0 / 3.0))) ** 2.0 37 | ) 38 | t1 = 1.0 + mu * st2 / R 39 | return 1.0 + R - R / t1 40 | 41 | 42 | def _omega(z): 43 | # return (ufunc(z, 4.0 / 3.0) - 2.0) / 0.5198421 44 | return (ufunc(z, 4.0 / 3.0) - 2.0) / (2.0 * 2.0 ** (1.0 / 3.0) - 2.0) 45 | 46 | 47 | def _eopt(sqrtr, t): 48 | return ( 49 | -2.0 50 | * t[0] 51 | * (1.0 + t[1] * sqrtr * sqrtr) 52 | * np.log( 53 | 1.0 54 | + 0.5 55 | / (t[0] * (sqrtr * (t[2] + sqrtr * (t[3] + sqrtr * (t[4] + t[5] * sqrtr))))) 56 | ) 57 | ) 58 | 59 | 60 | def _pw92eps(zeta, r_s): 61 | parameters = [ 62 | [0.03109070, 0.21370, 7.59570, 3.5876, 1.63820, 0.49294], 63 | [0.01554535, 0.20548, 14.1189, 6.1977, 3.36620, 0.62517], 64 | [0.01688690, 0.11125, 10.3570, 3.6231, 0.88026, 0.49671], 65 | ] 66 | # c = 1.709921 67 | c = 8.0 / (9.0 * (2.0 * 2.0 ** (1.0 / 3.0) - 2.0)) 68 | zeta4 = zeta ** 4.0 69 | omegaval = _omega(zeta) 70 | sqrtr = r_s ** 0.5 71 | e0 = _eopt(sqrtr, parameters[0]) 72 | return ( 73 | e0 74 | - _eopt(sqrtr, parameters[2]) * omegaval * (1.0 - zeta4) / c 75 | + (_eopt(sqrtr, parameters[1]) - e0) * omegaval * zeta4 76 | ) 77 | 78 | 79 | def _A(eps, u3): 80 | return param_beta_gamma / (np.exp(-eps / (param_gamma * u3)) - 1.0) 81 | 82 | 83 | # This is [(1+zeta)^(2/3) + (1-zeta)^(2/3)]/2, reorganized. 84 | def _phi(a, b): 85 | n = a + b 86 | c = 2.0 ** (-1.0 / 3.0) 87 | n_m13 = n ** (-1.0 / 3.0) 88 | a_43 = a ** (2.0 / 3.0) 89 | b_43 = b ** (2.0 / 3.0) 90 | return c * n_m13 * n_m13 * (a_43 + b_43) 91 | 92 | 93 | def _H(d2, eps, u3): 94 | d2A = d2 * _A(eps, u3) 95 | return ( 96 | param_gamma 97 | * u3 98 | * np.log(1.0 + param_beta_gamma * d2 * (1.0 + d2A) / (1.0 + d2A * (1.0 + d2A))) 99 | ) 100 | 101 | 102 | def _pbec(a, b, gnn): 103 | n = a + b 104 | s = a - b 105 | zeta = s / n 106 | r_s = (3.0 / (4.0 * np.pi * n)) ** (1.0 / 3.0) 107 | eps = _pw92eps(zeta, r_s) 108 | u = _phi(a, b) 109 | d2 = ( 110 | (1.0 / 12.0 * 3.0 ** (5.0 / 6.0) / np.pi ** (-1.0 / 6.0)) ** 2.0 111 | * gnn 112 | / (u * u * n ** (7.0 / 3.0)) 113 | ) 114 | u3 = u * u * u 115 | return n * (eps + _H(d2, eps, u3)) 116 | 117 | 118 | def pbex_a_gaa(a, gaa): 119 | R = 0.804 120 | return _prefactor(a) * _enhancement(R, a, gaa) 121 | 122 | 123 | def pbex_n_gnn(n, gnn): 124 | gaa = 0.25 * gnn 125 | gbb = gaa 126 | a = 0.5 * n 127 | b = 0.5 * n 128 | 129 | return pbex_a_gaa(a, gaa) + pbex_a_gaa(b, gbb) 130 | 131 | 132 | def pbex_a_b_gaa_gbb(a, b, gaa, gbb): 133 | return pbex_a_gaa(a, gaa) + pbex_a_gaa(b, gbb) 134 | 135 | 136 | def pbec_n_gnn(n, gnn): 137 | a = 0.5 * n 138 | b = 0.5 * n 139 | return _pbec(a, b, gnn) 140 | 141 | 142 | def pbec_a_b_gaa_gab_gbb(a, b, gaa, gab, gbb): 143 | gnn = gaa + 2.0 * gab + gbb 144 | return _pbec(a, b, gnn) 145 | -------------------------------------------------------------------------------- /xcauto/functionals/slater.py: -------------------------------------------------------------------------------- 1 | import jax.numpy as np 2 | 3 | 4 | def slaterx_a(a): 5 | cx = (-3.0 / 4.0) * (6.0 / np.pi) ** (1.0 / 3.0) 6 | return cx * a ** (4.0 / 3.0) 7 | 8 | 9 | def slaterx_a_b(a, b): 10 | return slaterx_a(a) + slaterx_a(b) 11 | 12 | 13 | def slaterx_n(n): 14 | return slaterx_a_b(0.5 * n, 0.5 * n) 15 | -------------------------------------------------------------------------------- /xcauto/functionals/utils.py: -------------------------------------------------------------------------------- 1 | def ufunc(x, a): 2 | return (1.0 + x) ** a + (1.0 - x) ** a 3 | -------------------------------------------------------------------------------- /xcauto/functionals/vwn.py: -------------------------------------------------------------------------------- 1 | # The functional definition in this file was ported to Python 2 | # from XCFun, which is Copyright Ulf Ekström and contributors 2009-2020 3 | # and provided under the Mozilla Public License (v2.0) 4 | # see also: 5 | # - https://github.com/dftlibs/xcfun 6 | # - https://github.com/dftlibs/xcfun/blob/master/LICENSE.md 7 | 8 | 9 | import jax.numpy as np 10 | 11 | from .utils import ufunc 12 | 13 | 14 | def _vwn_a(p): 15 | return p[0] * p[2] / (p[0] * p[0] + p[0] * p[2] + p[3]) - 1.0 16 | 17 | 18 | def _vwn_b(p): 19 | return 2.0 * (p[0] * p[2] / (p[0] * p[0] + p[0] * p[2] + p[3]) - 1) + 2.0 20 | 21 | 22 | def _vwn_c(p): 23 | return ( 24 | 2.0 25 | * p[2] 26 | * ( 27 | 1.0 / np.sqrt(4.0 * p[3] - p[2] * p[2]) 28 | - p[0] 29 | / ( 30 | (p[0] * p[0] + p[0] * p[2] + p[3]) 31 | * np.sqrt(4.0 * p[3] - p[2] * p[2]) 32 | / (p[2] + 2.0 * p[0]) 33 | ) 34 | ) 35 | ) 36 | 37 | 38 | def _vwn_x(s, p): 39 | return s * s + p[2] * s + p[3] 40 | 41 | 42 | def _vwn_y(s, p): 43 | return s - p[0] 44 | 45 | 46 | def _vwn_z(s, p): 47 | return np.sqrt(4.0 * p[3] - p[2] * p[2]) / (2.0 * s + p[2]) 48 | 49 | 50 | def _vwn_f(s, p): 51 | return ( 52 | 0.5 53 | * p[1] 54 | * ( 55 | 2.0 * np.log(s) 56 | + _vwn_a(p) * np.log(_vwn_x(s, p)) 57 | - _vwn_b(p) * np.log(_vwn_y(s, p)) 58 | + _vwn_c(p) * np.arctan(_vwn_z(s, p)) 59 | ) 60 | ) 61 | 62 | 63 | def vwn5_n(n): 64 | return vwn5_a_b(0.5 * n, 0.5 * n) 65 | 66 | 67 | def vwn5_a_b(a, b): 68 | para = [-0.10498, 0.0621813817393097900698817274255, 3.72744, 12.9352] 69 | ferro = [-0.325, 0.0310906908696548950349408637127, 7.06042, 18.0578] 70 | inter = [-0.0047584, -1.0 / (3.0 * np.pi * np.pi), 1.13107, 13.0045] 71 | 72 | n = a + b 73 | 74 | r_s = (3.0 / (4.0 * np.pi * n)) ** (1.0 / 3.0) 75 | s = r_s ** 0.5 76 | 77 | zeta = (a - b) / n 78 | g = 1.92366105093154 * (ufunc(zeta, 4.0 / 3.0) - 2.0) 79 | zeta4 = zeta ** 4.0 80 | dd = g * ( 81 | (_vwn_f(s, ferro) - _vwn_f(s, para)) * zeta4 82 | + _vwn_f(s, inter) * (1.0 - zeta4) * (9.0 / 4.0 * (2.0 ** (1.0 / 3.0) - 1.0)) 83 | ) 84 | 85 | return n * (_vwn_f(s, para) + dd) 86 | 87 | 88 | def vwn3_n(n): 89 | return vwn3_a_b(0.5 * n, 0.5 * n) 90 | 91 | 92 | def vwn3_a_b(a, b): 93 | para = [-0.4092860, 0.0621814, 13.0720, 42.7198] 94 | ferro = [-0.7432940, 0.0310907, 20.1231, 101.578] 95 | inter = [-0.0047584, -0.0337737, 1.13107, 13.0045] 96 | 97 | n = a + b 98 | 99 | r_s = (3.0 / (4.0 * np.pi * n)) ** (1.0 / 3.0) 100 | s = r_s ** 0.5 101 | 102 | zeta = (a - b) / n 103 | g = 1.92366105093154 * (ufunc(zeta, 4.0 / 3.0) - 2.0) 104 | zeta4 = zeta ** 4.0 105 | dd = g * (_vwn_f(s, ferro) - _vwn_f(s, para)) 106 | 107 | return n * (_vwn_f(s, para) + dd) 108 | --------------------------------------------------------------------------------