├── .coveragerc
├── .docker
├── cp2k-code.yml
├── init
│ └── add-codes.sh
├── s6-rc.d
│ └── cp2k-code-setup
│ │ ├── dependencies.d
│ │ └── aiida-prepare
│ │ ├── timeout-up
│ │ ├── type
│ │ └── up
└── user
│ └── cp2k-code-setup
├── .flake8
├── .github
└── workflows
│ ├── ci.yml
│ └── publish.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .readthedocs.yml
├── Dockerfile
├── LICENSE.txt
├── README.md
├── aiida-cp2k_logo.svg
├── aiida_cp2k
├── __init__.py
├── calculations
│ └── __init__.py
├── parsers
│ └── __init__.py
├── utils
│ ├── __init__.py
│ ├── datatype_helpers.py
│ ├── input_generator.py
│ ├── parser.py
│ └── workchains.py
└── workchains
│ ├── __init__.py
│ └── base.py
├── conftest.py
├── docs
├── .gitignore
├── Makefile
└── source
│ ├── _static
│ └── style.css
│ ├── _templates
│ └── layout.html
│ ├── apidoc
│ └── .gitignore
│ ├── conf.py
│ ├── examples.rst
│ ├── features.rst
│ ├── images
│ └── AiiDA_transparent_logo.png
│ ├── index.rst
│ └── workflows.rst
├── examples
├── files
│ ├── BASIS_MOLOPT
│ ├── GTH_POTENTIALS
│ ├── h2.xyz
│ ├── h2o.xyz
│ └── si.xyz
├── gaussian_datatypes
│ ├── example_automatic.py
│ ├── example_explicit.py
│ └── gdt_data.py
├── single_calculations
│ ├── example_bands.py
│ ├── example_dft.py
│ ├── example_dft_atomic_kinds.py
│ ├── example_failure.py
│ ├── example_geopt.py
│ ├── example_geopt_advanced_parser.py
│ ├── example_max_error.py
│ ├── example_mm.py
│ ├── example_mm_md.py
│ ├── example_multiple_force_eval.py
│ ├── example_no_struct.py
│ ├── example_precision.py
│ ├── example_restart.py
│ ├── example_sirius.py
│ └── example_structure_through_file.py
└── workchains
│ ├── example_base_energy_restart.py
│ ├── example_base_failed_restart.py
│ ├── example_base_geo_opt_ignore_converge_restart.py
│ ├── example_base_geoopt_restart.py
│ ├── example_base_md_restart.py
│ └── fixme_example_base_md_reftraj_restart.py
├── miscellaneous
└── logos
│ ├── MARVEL.png
│ ├── MaX.png
│ └── swissuniversities.png
├── pyproject.toml
└── test
├── outputs
├── BANDS_output_v5.1.out
├── BANDS_output_v8.1.out
├── BSSE_output_v5.1_.out
├── GEO_OPT_v2024.3.out
├── GEO_OPT_v9.1.out
├── OT_v9.1.out
├── PBC_output_none.restart
├── PBC_output_xyz.restart
├── PBC_output_xz.restart
├── cdft_dos_cp2k_6.0.out
└── tddft_cp2k_6.0.out
├── test_datatype_helpers.py
├── test_gaussian_datatypes.py
├── test_input_generator.py
├── test_parser.py
└── test_xyz.py
/.coveragerc:
--------------------------------------------------------------------------------
1 | [run]
2 | parallel=True
3 |
--------------------------------------------------------------------------------
/.docker/cp2k-code.yml:
--------------------------------------------------------------------------------
1 | label: cp2k
2 | computer: localhost
3 | description:
4 | default_calc_job_plugin: cp2k
5 | filepath_executable: /opt/conda/envs/cp2k/bin/cp2k.psmp
6 | append_text:
7 | prepend_text: |
8 | eval "$(command conda shell.bash hook 2> /dev/null)"
9 | conda activate cp2k
10 |
--------------------------------------------------------------------------------
/.docker/init/add-codes.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 |
3 | # Debugging
4 | set -x
5 |
6 | # Environment
7 | export SHELL=/bin/bash
8 |
9 | # Install cp2k code.
10 | verdi code show cp2k@localhost || verdi code create core.code.installed --config /home/aiida/aiida-cp2k/.docker/cp2k-code.yml --non-interactive
11 |
--------------------------------------------------------------------------------
/.docker/s6-rc.d/cp2k-code-setup/dependencies.d/aiida-prepare:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiidateam/aiida-cp2k/c6b973e774c327066037544cff2e07f80a5fb4a4/.docker/s6-rc.d/cp2k-code-setup/dependencies.d/aiida-prepare
--------------------------------------------------------------------------------
/.docker/s6-rc.d/cp2k-code-setup/timeout-up:
--------------------------------------------------------------------------------
1 | 0
2 |
--------------------------------------------------------------------------------
/.docker/s6-rc.d/cp2k-code-setup/type:
--------------------------------------------------------------------------------
1 | oneshot
2 |
--------------------------------------------------------------------------------
/.docker/s6-rc.d/cp2k-code-setup/up:
--------------------------------------------------------------------------------
1 | #!/command/execlineb -S0
2 |
3 | with-contenv
4 |
5 | foreground { s6-echo "Setting up CP2K code" }
6 |
7 | /etc/init/add-codes.sh
8 |
--------------------------------------------------------------------------------
/.docker/user/cp2k-code-setup:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiidateam/aiida-cp2k/c6b973e774c327066037544cff2e07f80a5fb4a4/.docker/user/cp2k-code-setup
--------------------------------------------------------------------------------
/.flake8:
--------------------------------------------------------------------------------
1 | [flake8]
2 | max-line-length = 88
3 | extend-ignore =
4 | E501
5 | W503
6 | E203
7 | exclude =
8 | docs/source/conf.py
9 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Continuous Integration
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 |
9 | jobs:
10 |
11 | test-plugin:
12 |
13 | runs-on: ubuntu-latest
14 | strategy:
15 | matrix:
16 | aiida-version:
17 | - '2.4.3'
18 | - '2.5.1'
19 |
20 | timeout-minutes: 30
21 |
22 | steps:
23 |
24 | - uses: actions/checkout@v2
25 |
26 | - name: Set up Docker Buildx
27 | uses: docker/setup-buildx-action@v1
28 |
29 | # see https://github.com/docker/build-push-action/blob/master/docs/advanced/cache.md#github-cache
30 | - name: Cache Docker layers
31 | uses: actions/cache@v2
32 | with:
33 | path: /tmp/.buildx-cache
34 | key: ${{ runner.os }}-buildx-${{ github.sha }}
35 | restore-keys: |
36 | ${{ runner.os }}-buildx-
37 |
38 | - name: Build
39 | uses: docker/build-push-action@v2
40 | with:
41 | context: .
42 | push: false
43 | load: true
44 | tags: aiida_cp2k_test
45 | cache-from: type=local,src=/tmp/.buildx-cache
46 | cache-to: type=local,dest=/tmp/.buildx-cache-new
47 | build-args: |
48 | AIIDA_VERSION=${{ matrix.aiida-version }}
49 |
50 | # Temp fix
51 | # https://github.com/docker/build-push-action/issues/252
52 | # https://github.com/moby/buildkit/issues/1896
53 | - name: Move cache
54 | run: |
55 | rm -rf /tmp/.buildx-cache
56 | mv /tmp/.buildx-cache-new /tmp/.buildx-cache
57 |
58 | - name: Create container from aiida_cp2k_test image and test the plugin inside
59 | run: |
60 | export DOCKERID=`docker run -d aiida_cp2k_test`
61 | sleep 5
62 | docker logs $DOCKERID
63 | docker exec --tty --user aiida $DOCKERID /bin/bash -l -c 'cd /home/aiida/aiida-cp2k/ && py.test --cov aiida_cp2k --cov-append .'
64 |
65 |
66 | docs:
67 | runs-on: ubuntu-latest
68 | timeout-minutes: 10
69 | strategy:
70 | matrix:
71 | python-version: [3.11]
72 | steps:
73 | - uses: actions/checkout@v2
74 | - name: Set up Python ${{ matrix.python-version }}
75 | uses: actions/setup-python@v2
76 | with:
77 | python-version: ${{ matrix.python-version }}
78 | - name: Install python dependencies
79 | run: |
80 | pip install --upgrade pip
81 | pip install -e .[docs,dev]
82 |
83 | - name: Build docs
84 | run: cd docs && make
85 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Publish on PyPI
3 |
4 | on:
5 | push:
6 | tags:
7 | # After vMajor.Minor.Patch _anything_ is allowed (without "/") !
8 | - v[0-9]+.[0-9]+.[0-9]+*
9 |
10 | jobs:
11 | publish:
12 | runs-on: ubuntu-latest
13 | if: github.repository == 'aiidateam/aiida-cp2k'
14 |
15 | steps:
16 | - name: Checkout source
17 | uses: actions/checkout@v2
18 | - name: Set up Python 3.8
19 | uses: actions/setup-python@v2
20 | with:
21 | python-version: '3.8'
22 | - name: Install flit
23 | run: pip install flit~=3.4
24 | - name: Build and publish
25 | run: flit publish
26 | env:
27 | FLIT_USERNAME: __token__
28 | FLIT_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
29 | - uses: softprops/action-gh-release@v0.1.14
30 | name: Create release
31 | with:
32 | files: |
33 | dist/*
34 | generate_release_notes: true
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/vim,linux,macos,python,pycharm
3 | # Edit at https://www.gitignore.io/?templates=vim,linux,macos,python,pycharm
4 |
5 | ### Linux ###
6 | *~
7 |
8 | # temporary files which can be created if a process still has a handle open of a deleted file
9 | .fuse_hidden*
10 |
11 | # KDE directory preferences
12 | .directory
13 |
14 | # Linux trash folder which might appear on any partition or disk
15 | .Trash-*
16 |
17 | # .nfs files are created when an open file is removed but is still being accessed
18 | .nfs*
19 |
20 | ### macOS ###
21 | # General
22 | .DS_Store
23 | .AppleDouble
24 | .LSOverride
25 |
26 | # Icon must end with two \r
27 | Icon
28 |
29 | # Thumbnails
30 | ._*
31 |
32 | # Files that might appear in the root of a volume
33 | .DocumentRevisions-V100
34 | .fseventsd
35 | .Spotlight-V100
36 | .TemporaryItems
37 | .Trashes
38 | .VolumeIcon.icns
39 | .com.apple.timemachine.donotpresent
40 |
41 | # Directories potentially created on remote AFP share
42 | .AppleDB
43 | .AppleDesktop
44 | Network Trash Folder
45 | Temporary Items
46 | .apdisk
47 |
48 | ### PyCharm ###
49 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
50 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
51 |
52 | # User-specific stuff
53 | .idea/**/workspace.xml
54 | .idea/**/tasks.xml
55 | .idea/**/usage.statistics.xml
56 | .idea/**/dictionaries
57 | .idea/**/shelf
58 |
59 | # Generated files
60 | .idea/**/contentModel.xml
61 |
62 | # Sensitive or high-churn files
63 | .idea/**/dataSources/
64 | .idea/**/dataSources.ids
65 | .idea/**/dataSources.local.xml
66 | .idea/**/sqlDataSources.xml
67 | .idea/**/dynamic.xml
68 | .idea/**/uiDesigner.xml
69 | .idea/**/dbnavigator.xml
70 |
71 | # Gradle
72 | .idea/**/gradle.xml
73 | .idea/**/libraries
74 |
75 | # Gradle and Maven with auto-import
76 | # When using Gradle or Maven with auto-import, you should exclude module files,
77 | # since they will be recreated, and may cause churn. Uncomment if using
78 | # auto-import.
79 | # .idea/modules.xml
80 | # .idea/*.iml
81 | # .idea/modules
82 | # *.iml
83 | # *.ipr
84 |
85 | # CMake
86 | cmake-build-*/
87 |
88 | # Mongo Explorer plugin
89 | .idea/**/mongoSettings.xml
90 |
91 | # File-based project format
92 | *.iws
93 |
94 | # IntelliJ
95 | out/
96 |
97 | # mpeltonen/sbt-idea plugin
98 | .idea_modules/
99 |
100 | # JIRA plugin
101 | atlassian-ide-plugin.xml
102 |
103 | # Cursive Clojure plugin
104 | .idea/replstate.xml
105 |
106 | # Crashlytics plugin (for Android Studio and IntelliJ)
107 | com_crashlytics_export_strings.xml
108 | crashlytics.properties
109 | crashlytics-build.properties
110 | fabric.properties
111 |
112 | # Editor-based Rest Client
113 | .idea/httpRequests
114 |
115 | # Android studio 3.1+ serialized cache file
116 | .idea/caches/build_file_checksums.ser
117 |
118 | ### PyCharm Patch ###
119 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
120 |
121 | # *.iml
122 | # modules.xml
123 | # .idea/misc.xml
124 | # *.ipr
125 |
126 | # Sonarlint plugin
127 | .idea/sonarlint
128 |
129 | ### Python ###
130 | # Byte-compiled / optimized / DLL files
131 | __pycache__/
132 | *.py[cod]
133 | *$py.class
134 |
135 | # C extensions
136 | *.so
137 |
138 | # Distribution / packaging
139 | .Python
140 | build/
141 | develop-eggs/
142 | dist/
143 | downloads/
144 | eggs/
145 | .eggs/
146 | lib/
147 | lib64/
148 | parts/
149 | sdist/
150 | var/
151 | wheels/
152 | pip-wheel-metadata/
153 | share/python-wheels/
154 | *.egg-info/
155 | .installed.cfg
156 | *.egg
157 | MANIFEST
158 |
159 | # PyInstaller
160 | # Usually these files are written by a python script from a template
161 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
162 | *.manifest
163 | *.spec
164 |
165 | # Installer logs
166 | pip-log.txt
167 | pip-delete-this-directory.txt
168 |
169 | # Unit test / coverage reports
170 | htmlcov/
171 | .tox/
172 | .nox/
173 | .coverage
174 | .coverage.*
175 | .cache
176 | nosetests.xml
177 | coverage.xml
178 | *.cover
179 | .hypothesis/
180 | .pytest_cache/
181 |
182 | # Translations
183 | *.mo
184 | *.pot
185 |
186 | # Django stuff:
187 | *.log
188 | local_settings.py
189 | db.sqlite3
190 | db.sqlite3-journal
191 |
192 | # Flask stuff:
193 | instance/
194 | .webassets-cache
195 |
196 | # Scrapy stuff:
197 | .scrapy
198 |
199 | # Sphinx documentation
200 | docs/_build/
201 |
202 | # PyBuilder
203 | target/
204 |
205 | # Jupyter Notebook
206 | .ipynb_checkpoints
207 |
208 | # IPython
209 | profile_default/
210 | ipython_config.py
211 |
212 | # pyenv
213 | .python-version
214 |
215 | # pipenv
216 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
217 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
218 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
219 | # install all needed dependencies.
220 | #Pipfile.lock
221 |
222 | # celery beat schedule file
223 | celerybeat-schedule
224 |
225 | # SageMath parsed files
226 | *.sage.py
227 |
228 | # Environments
229 | .env
230 | .venv
231 | env/
232 | venv/
233 | ENV/
234 | env.bak/
235 | venv.bak/
236 |
237 | # Spyder project settings
238 | .spyderproject
239 | .spyproject
240 |
241 | # Rope project settings
242 | .ropeproject
243 |
244 | # mkdocs documentation
245 | /site
246 |
247 | # mypy
248 | .mypy_cache/
249 | .dmypy.json
250 | dmypy.json
251 |
252 | # Pyre type checker
253 | .pyre/
254 |
255 | ### Vim ###
256 | # Swap
257 | [._]*.s[a-v][a-z]
258 | [._]*.sw[a-p]
259 | [._]s[a-rt-v][a-z]
260 | [._]ss[a-gi-z]
261 | [._]sw[a-p]
262 |
263 | # Session
264 | Session.vim
265 | Sessionx.vim
266 |
267 | # Temporary
268 | .netrwhist
269 | # Auto-generated tag files
270 | tags
271 | # Persistent undo
272 | [._]*.un~
273 |
274 | # End of https://www.gitignore.io/api/vim,linux,macos,python,pycharm
275 |
276 | submit_test
277 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | ci:
3 | autoupdate_schedule: quarterly
4 |
5 | repos:
6 | - repo: https://github.com/pre-commit/pre-commit-hooks
7 | rev: v5.0.0
8 | hooks:
9 |
10 | - id: check-json
11 | - id: check-yaml
12 | - id: end-of-file-fixer
13 | exclude: &exclude_pre_commit_hooks >
14 | (?x)^(
15 | test/.*(?
97 |
98 |
99 |
--------------------------------------------------------------------------------
/aiida_cp2k/__init__.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """The official AiiDA plugin for CP2K."""
8 |
9 | __version__ = "2.1.1"
10 |
11 | # EOF
12 |
--------------------------------------------------------------------------------
/aiida_cp2k/utils/__init__.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """AiiDA-CP2K utils"""
8 |
9 | from .datatype_helpers import (
10 | merge_trajectory_data_non_unique,
11 | merge_trajectory_data_unique,
12 | )
13 | from .input_generator import (
14 | Cp2kInput,
15 | add_ext_restart_section,
16 | add_first_snapshot_in_reftraj_section,
17 | add_ignore_convergence_failure,
18 | add_wfn_restart_section,
19 | increase_geo_opt_max_iter_by_factor,
20 | )
21 | from .parser import parse_cp2k_output, parse_cp2k_output_advanced, parse_cp2k_trajectory
22 | from .workchains import (
23 | HARTREE2EV,
24 | HARTREE2KJMOL,
25 | check_resize_unit_cell,
26 | get_input_multiplicity,
27 | get_kinds_section,
28 | get_last_convergence_value,
29 | merge_dict,
30 | merge_Dict,
31 | ot_has_small_bandgap,
32 | resize_unit_cell,
33 | )
34 |
35 | __all__ = [
36 | "Cp2kInput",
37 | "add_ext_restart_section",
38 | "add_ignore_convergence_failure",
39 | "add_first_snapshot_in_reftraj_section",
40 | "add_wfn_restart_section",
41 | "check_resize_unit_cell",
42 | "get_input_multiplicity",
43 | "get_kinds_section",
44 | "get_last_convergence_value",
45 | "HARTREE2EV",
46 | "HARTREE2KJMOL",
47 | "increase_geo_opt_max_iter_by_factor",
48 | "merge_dict",
49 | "merge_Dict",
50 | "merge_trajectory_data_unique",
51 | "merge_trajectory_data_non_unique",
52 | "ot_has_small_bandgap",
53 | "parse_cp2k_output",
54 | "parse_cp2k_output_advanced",
55 | "parse_cp2k_trajectory",
56 | "resize_unit_cell",
57 | ]
58 |
--------------------------------------------------------------------------------
/aiida_cp2k/utils/input_generator.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """AiiDA-CP2K input generator."""
8 |
9 | from collections.abc import Mapping, MutableMapping, MutableSequence, Sequence
10 | from copy import deepcopy
11 |
12 | from aiida.engine import calcfunction
13 | from aiida.orm import Dict
14 |
15 | from .workchains import merge_dict
16 |
17 |
18 | class Cp2kInput:
19 | """Transforms dictionary into CP2K input"""
20 |
21 | DISCLAIMER = "!!! Generated by AiiDA !!!"
22 |
23 | def __init__(self, params=None):
24 | """Initializing Cp2kInput object"""
25 | if not params:
26 | self._params = {}
27 | else:
28 | # always make a full copy to avoid that add_keyword() changes the
29 | # passed-in dictionary
30 | self._params = deepcopy(params)
31 |
32 | def __getitem__(self, key):
33 | return self._params[key]
34 |
35 | def add_keyword(self, kwpath, value, override=True, conflicting_keys=None):
36 | """
37 | Add a value for the given keyword.
38 |
39 | Args:
40 |
41 | kwpath: Can be a single keyword, a path with `/` as divider for sections & key,
42 | or a sequence with sections and key.
43 |
44 | value: the value to set the given key to
45 |
46 | override: whether to override the key if it is already present in the self._params
47 |
48 | conflicting_keys: list of keys that cannot live together with the provided key
49 | (SOMETHING1/[..]/SOMETHING2/KEY). In case override is True, all conflicting keys will
50 | be removed, if override is False and conflicting_keys are present the new key won't be
51 | added.
52 | """
53 |
54 | if isinstance(kwpath, str):
55 | kwpath = kwpath.split("/")
56 |
57 | Cp2kInput._add_keyword(
58 | kwpath, value, self._params, ovrd=override, cfct=conflicting_keys
59 | )
60 |
61 | def render(self):
62 | output = [self.DISCLAIMER]
63 | self._render_section(output, deepcopy(self._params))
64 | return "\n".join(output)
65 |
66 | def param_iter(self, sections=True):
67 | """Iterator yielding ((section,section,...,section/keyword), value) tuples"""
68 | stack = [((k,), v) for k, v in self._params.items()]
69 |
70 | while stack:
71 | key, value = stack.pop(0)
72 | if isinstance(value, Mapping):
73 | if sections:
74 | yield (key, value)
75 | stack += [(key + (k,), v) for k, v in value.items()]
76 | elif isinstance(
77 | value, MutableSequence
78 | ): # not just 'Sequence' to avoid matching strings
79 | for entry in value:
80 | stack += [(key, entry)]
81 | else:
82 | yield (key, value)
83 |
84 | @staticmethod
85 | def _add_keyword(kwpath, value, params, ovrd, cfct):
86 | """Add keyword into the given nested dictionary"""
87 | conflicting_keys_present = []
88 | # key/value for the deepest level
89 | if len(kwpath) == 1:
90 | if cfct:
91 | conflicting_keys_present = [key for key in cfct if key in params]
92 | if (
93 | ovrd
94 | ): # if ovrd is True, set the new element's value and remove the conflicting keys
95 | params[kwpath[0]] = value
96 | for key in conflicting_keys_present:
97 | params.pop(key)
98 | # if ovrd is False, I only add the new key if (1) it wasn't present beforeAND (2) it does not conflict
99 | # with any key that is currently present
100 | elif not conflicting_keys_present and kwpath[0] not in params:
101 | params[kwpath[0]] = value
102 |
103 | # the key was not present in the dictionary, and we are not yet at the deepest level,
104 | # therefore a subdictionary should be added
105 | elif kwpath[0] not in params:
106 | params[kwpath[0]] = {}
107 | Cp2kInput._add_keyword(kwpath[1:], value, params[kwpath[0]], ovrd, cfct)
108 |
109 | # if it is a list, loop over its elements
110 | elif isinstance(params[kwpath[0]], Sequence) and not isinstance(
111 | params[kwpath[0]], str
112 | ):
113 | for element in params[kwpath[0]]:
114 | Cp2kInput._add_keyword(kwpath[1:], value, element, ovrd, cfct)
115 |
116 | # if the key does NOT point to a dictionary and we are not yet at the deepest level,
117 | # therefore, the element should be replaced with an empty dictionary unless ovrd is False
118 | elif not isinstance(params[kwpath[0]], Mapping):
119 | if ovrd:
120 | params[kwpath[0]] = {}
121 | Cp2kInput._add_keyword(kwpath[1:], value, params[kwpath[0]], ovrd, cfct)
122 | # if params[kwpath[0]] points to a sub-dictionary, enter into it
123 | else:
124 | Cp2kInput._add_keyword(kwpath[1:], value, params[kwpath[0]], ovrd, cfct)
125 |
126 | @staticmethod
127 | def _render_section(output, params, indent=0):
128 | """It takes a dictionary and recurses through.
129 |
130 | For key-value pair it checks whether the value is a dictionary and prepends the key with & (CP2K section).
131 | It passes the valued to the same function, increasing the indentation. If the value is a list, I assume
132 | that this is something the user wants to store repetitively
133 | eg:
134 | .. highlight::
135 |
136 | dict['KEY'] = ['val1', 'val2']
137 | ===>
138 | KEY val1
139 | KEY val2
140 |
141 | or
142 |
143 | dict['KIND'] = [{'_': 'Ba', 'ELEMENT':'Ba'},
144 | {'_': 'Ti', 'ELEMENT':'Ti'},
145 | {'_': 'O', 'ELEMENT':'O'}]
146 | ====>
147 | &KIND Ba
148 | ELEMENT Ba
149 | &END KIND
150 | &KIND Ti
151 | ELEMENT Ti
152 | &END KIND
153 | &KIND O
154 | ELEMENT O
155 | &END KIND
156 | """
157 |
158 | for key, val in sorted(params.items()):
159 | # keys are not case-insensitive, ensure that they follow the current scheme
160 | if key.upper() != key:
161 | raise ValueError(f"keyword '{key}' not upper case.")
162 |
163 | if key.startswith(("@", "$")):
164 | raise ValueError("CP2K preprocessor directives not supported.")
165 |
166 | if isinstance(val, MutableMapping):
167 | line = f"{' ' * indent}&{key}"
168 | if "_" in val: # if there is a section parameter, add it
169 | line += f" {val.pop('_')}"
170 | output.append(line)
171 | Cp2kInput._render_section(output, val, indent + 3)
172 | output.append(f"{' ' * indent}&END {key}")
173 |
174 | elif isinstance(val, Sequence) and not isinstance(val, str):
175 | for listitem in val:
176 | Cp2kInput._render_section(output, {key: listitem}, indent)
177 |
178 | elif isinstance(val, bool):
179 | val_str = ".TRUE." if val else ".FALSE."
180 | output.append(f"{' ' * indent}{key} {val_str}")
181 |
182 | else:
183 | output.append(f"{' ' * indent}{key} {val}")
184 |
185 |
186 | @calcfunction
187 | def add_wfn_restart_section(input_dict, is_kpoints):
188 | """Add wavefunction restart section to the input dictionary."""
189 | params = input_dict.get_dict()
190 | fname = (
191 | "./parent_calc/aiida-RESTART.kp"
192 | if is_kpoints
193 | else "./parent_calc/aiida-RESTART.wfn"
194 | )
195 | restart_wfn_dict = {
196 | "FORCE_EVAL": {
197 | "DFT": {
198 | "RESTART_FILE_NAME": fname,
199 | "SCF": {
200 | "SCF_GUESS": "RESTART",
201 | },
202 | },
203 | },
204 | }
205 | merge_dict(params, restart_wfn_dict)
206 | return Dict(params)
207 |
208 |
209 | @calcfunction
210 | def add_ext_restart_section(input_dict):
211 | """Add external restart section to the input dictionary."""
212 | params = input_dict.get_dict()
213 | # overwrite the complete EXT_RESTART section if present
214 | params["EXT_RESTART"] = {
215 | "RESTART_FILE_NAME": "./parent_calc/aiida-1.restart",
216 | "RESTART_DEFAULT": ".TRUE.",
217 | "RESTART_COUNTERS": ".TRUE.",
218 | "RESTART_POS": ".TRUE.",
219 | "RESTART_VEL": ".TRUE.",
220 | "RESTART_CELL": ".TRUE.",
221 | "RESTART_THERMOSTAT": ".TRUE.",
222 | "RESTART_CONSTRAINT": ".FALSE.",
223 | }
224 | return Dict(params)
225 |
226 |
227 | @calcfunction
228 | def add_first_snapshot_in_reftraj_section(input_dict, first_snapshot):
229 | """Add first_snapshot in REFTRAJ section to the input dictionary."""
230 | params = input_dict.get_dict()
231 | params["MOTION"]["MD"]["REFTRAJ"]["FIRST_SNAPSHOT"] = first_snapshot
232 | return Dict(params)
233 |
234 |
235 | @calcfunction
236 | def increase_geo_opt_max_iter_by_factor(input_dict, factor):
237 | """Increase the MAX_ITER in GEO_OPT section by a factor."""
238 | params = input_dict.get_dict()
239 | params.setdefault("MOTION", {}).setdefault("GEO_OPT", {})["MAX_ITER"] = int(
240 | factor * params.get("MOTION", {}).get("GEO_OPT", {}).get("MAX_ITER", 100)
241 | )
242 | return Dict(params)
243 |
244 |
245 | @calcfunction
246 | def add_ignore_convergence_failure(input_dict):
247 | """Add IGNORE_CONVERGENCE_FAILURE for non converged SCF runs."""
248 | params = input_dict.get_dict()
249 | params.setdefault("FORCE_EVAL", {}).setdefault("DFT", {}).setdefault("SCF", {})[
250 | "IGNORE_CONVERGENCE_FAILURE"
251 | ] = ".TRUE."
252 | return Dict(params)
253 |
--------------------------------------------------------------------------------
/aiida_cp2k/utils/workchains.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """AiiDA-CP2K utilities for workchains"""
8 |
9 | import re
10 |
11 | from aiida.engine import calcfunction
12 | from aiida.orm import Dict
13 | from aiida.plugins import DataFactory
14 |
15 | StructureData = DataFactory("core.structure")
16 |
17 | HARTREE2EV = 27.211399
18 | HARTREE2KJMOL = 2625.500
19 |
20 |
21 | def merge_dict(dct, merge_dct):
22 | """Taken from https://gist.github.com/angstwad/bf22d1822c38a92ec0a9
23 | Recursive dict merge. Inspired by :meth:``dict.update()``, instead of
24 | updating only top-level keys, merge_dict recurses down into dicts nested
25 | to an arbitrary depth, updating keys. The ``merge_dct`` is merged into
26 | ``dct``.
27 | :param dct: dict onto which the merge is executed
28 | :param merge_dct: dct merged into dct (overwrites dct data if in both)
29 | :return: None
30 | """
31 | from collections.abc import Mapping
32 |
33 | for k, _ in merge_dct.items(): # it was .iteritems() in python2
34 | if k in dct and isinstance(dct[k], dict) and isinstance(merge_dct[k], Mapping):
35 | merge_dict(dct[k], merge_dct[k])
36 | else:
37 | dct[k] = merge_dct[k]
38 |
39 |
40 | @calcfunction
41 | def merge_Dict(d1, d2):
42 | """Make all the data in the second Dict overwrite the corrisponding data in the first Dict"""
43 | d1_dict = d1.get_dict()
44 | d2_dict = d2.get_dict()
45 | merge_dict(d1_dict, d2_dict)
46 | return Dict(d1_dict)
47 |
48 |
49 | def get_kinds_section(structure, protocol_settings):
50 | """Write the &KIND sections given the structure and the settings_dict"""
51 | kinds = []
52 | all_atoms = set(structure.get_ase().get_chemical_symbols())
53 | for atom in all_atoms:
54 | kinds.append(
55 | {
56 | "_": atom,
57 | "BASIS_SET": protocol_settings["basis_set"][atom],
58 | "POTENTIAL": protocol_settings["pseudopotential"][atom],
59 | "MAGNETIZATION": protocol_settings["initial_magnetization"][atom],
60 | }
61 | )
62 | return {"FORCE_EVAL": {"SUBSYS": {"KIND": kinds}}}
63 |
64 |
65 | def get_input_multiplicity(structure, protocol_settings):
66 | """Compute the total multiplicity of the structure,
67 | by summing the atomic magnetizations:
68 | multiplicity = 1 + sum_i ( natoms_i * magnetization_i ), for each atom_type i
69 | """
70 | multiplicity = 1
71 | all_atoms = structure.get_ase().get_chemical_symbols()
72 | for key, value in protocol_settings["initial_magnetization"].items():
73 | multiplicity += all_atoms.count(key) * value
74 | multiplicity = int(round(multiplicity))
75 | multiplicity_dict = {"FORCE_EVAL": {"DFT": {"MULTIPLICITY": multiplicity}}}
76 | if multiplicity != 1:
77 | multiplicity_dict["FORCE_EVAL"]["DFT"]["UKS"] = True
78 | return multiplicity_dict
79 |
80 |
81 | def ot_has_small_bandgap(cp2k_input, cp2k_output, bandgap_thr_ev):
82 | """Returns True if the calculation used OT and had a smaller bandgap then the guess needed for the OT.
83 | (NOTE: It has been observed also negative bandgap with OT in CP2K!)
84 | cp2k_input: dict
85 | cp2k_output: dict
86 | bandgap_thr_ev: float [eV]
87 | """
88 | list_true = [True, "T", "t", ".TRUE.", "True", "true"] # add more?
89 | try:
90 | ot_settings = cp2k_input["FORCE_EVAL"]["DFT"]["SCF"]["OT"]
91 | if "_" not in ot_settings.keys() or ot_settings["_"] in list_true:
92 | using_ot = True
93 | else:
94 | using_ot = False
95 | except KeyError:
96 | using_ot = False
97 | min_bandgap_ev = (
98 | min(cp2k_output["bandgap_spin1_au"], cp2k_output["bandgap_spin2_au"])
99 | * HARTREE2EV
100 | )
101 | is_bandgap_small = min_bandgap_ev < bandgap_thr_ev
102 | return using_ot and is_bandgap_small
103 |
104 |
105 | def get_last_convergence_value(input_string):
106 | """Search for last "OT CG" and returns the SCF gradient.
107 |
108 | If no "OT CG", searches for last "DIIS/Diag" and returns the gradient.
109 |
110 | Args:
111 | input_string (str): the cp2k output string.
112 |
113 | Returns:
114 | float or None: the SCF gradient or None if not found.
115 | """
116 | # Search all "OT CG" lines and gets the 6th column.
117 | ot_cg_pattern = r"OT CG\s+\S+\s+\S+\s+\S+\s+\S+\s+([\d.E+-]+)"
118 | ot_cg_matches = re.findall(ot_cg_pattern, input_string)
119 |
120 | if ot_cg_matches:
121 | return float(ot_cg_matches[-1]) # Last value found for "OT CG".
122 |
123 | # Search for "DIIS/Diag" lines and returns the 5th column.
124 | diis_diag_pattern = r"DIIS/Diag\.\s+\S+\s+\S+\s+\S+\s+([\d.E+-]+)"
125 | diis_diag_matches = re.findall(diis_diag_pattern, input_string)
126 |
127 | if diis_diag_matches:
128 | return float(diis_diag_matches[-1]) # Last value found for "DIIS/Diag".
129 |
130 | return None # No value found.
131 |
132 |
133 | @calcfunction
134 | def check_resize_unit_cell(struct, threshold):
135 | """Returns the multiplication factors for the cell vectors to respect, in every direction:
136 | min(perpendicular_width) > threshold.
137 | """
138 | from math import ceil, cos, fabs, sin, sqrt
139 |
140 | import numpy as np
141 |
142 | # Parsing structure's cell
143 | def angle(vect1, vect2):
144 | return np.arccos(
145 | np.dot(vect1, vect2) / (np.linalg.norm(vect1) * np.linalg.norm(vect2))
146 | )
147 |
148 | a_len = np.linalg.norm(struct.cell[0])
149 | b_len = np.linalg.norm(struct.cell[1])
150 | c_len = np.linalg.norm(struct.cell[2])
151 |
152 | alpha = angle(struct.cell[1], struct.cell[2])
153 | beta = angle(struct.cell[0], struct.cell[2])
154 | gamma = angle(struct.cell[0], struct.cell[1])
155 |
156 | # Computing triangular cell matrix
157 | vol = np.sqrt(
158 | 1
159 | - cos(alpha) ** 2
160 | - cos(beta) ** 2
161 | - cos(gamma) ** 2
162 | + 2 * cos(alpha) * cos(beta) * cos(gamma)
163 | )
164 | cell = np.zeros((3, 3))
165 | cell[0, :] = [a_len, 0, 0]
166 | cell[1, :] = [b_len * cos(gamma), b_len * sin(gamma), 0]
167 | cell[2, :] = [
168 | c_len * cos(beta),
169 | c_len * (cos(alpha) - cos(beta) * cos(gamma)) / (sin(gamma)),
170 | c_len * vol / sin(gamma),
171 | ]
172 | cell = np.array(cell)
173 |
174 | # Computing perpendicular widths, as implemented in Raspa
175 | # for the check (simplified for triangular cell matrix)
176 | axc1 = cell[0, 0] * cell[2, 2]
177 | axc2 = -cell[0, 0] * cell[2, 1]
178 | bxc1 = cell[1, 1] * cell[2, 2]
179 | bxc2 = -cell[1, 0] * cell[2, 2]
180 | bxc3 = cell[1, 0] * cell[2, 1] - cell[1, 1] * cell[2, 0]
181 | det = fabs(cell[0, 0] * cell[1, 1] * cell[2, 2])
182 | perpwidth = np.zeros(3)
183 | perpwidth[0] = det / sqrt(bxc1**2 + bxc2**2 + bxc3**2)
184 | perpwidth[1] = det / sqrt(axc1**2 + axc2**2)
185 | perpwidth[2] = cell[2, 2]
186 |
187 | # prevent from crashing if threshold.value is zero
188 | if threshold.value == 0:
189 | thr = 0.1
190 | else:
191 | thr = threshold.value
192 |
193 | resize = {
194 | "nx": int(ceil(thr / perpwidth[0])),
195 | "ny": int(ceil(thr / perpwidth[1])),
196 | "nz": int(ceil(thr / perpwidth[2])),
197 | }
198 | return Dict(resize)
199 |
200 |
201 | @calcfunction
202 | def resize_unit_cell(struct, resize):
203 | """Resize the StructureData according to the resize Dict"""
204 | resize_tuple = tuple(resize[x] for x in ["nx", "ny", "nz"])
205 | return StructureData(ase=struct.get_ase().repeat(resize_tuple))
206 |
--------------------------------------------------------------------------------
/aiida_cp2k/workchains/__init__.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/cp2k/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """AiiDA-CP2K workchains"""
8 |
9 | from .base import Cp2kBaseWorkChain
10 |
11 | __all__ = ["Cp2kBaseWorkChain"]
12 |
--------------------------------------------------------------------------------
/aiida_cp2k/workchains/base.py:
--------------------------------------------------------------------------------
1 | """Base work chain to run a CP2K calculation."""
2 |
3 | import re
4 |
5 | from aiida import common, engine, orm, plugins
6 |
7 | from .. import utils
8 |
9 | Cp2kCalculation = plugins.CalculationFactory('cp2k')
10 |
11 |
12 | class Cp2kBaseWorkChain(engine.BaseRestartWorkChain):
13 | """Workchain to run a CP2K calculation with automated error handling and restarts."""
14 |
15 | _process_class = Cp2kCalculation
16 |
17 | @classmethod
18 | def define(cls, spec):
19 | # yapf: disable
20 | super().define(spec)
21 | spec.expose_inputs(Cp2kCalculation, namespace='cp2k')
22 |
23 | spec.outline(
24 | cls.setup,
25 | engine.while_(cls.should_run_process)(
26 | cls.run_process,
27 | cls.inspect_process,
28 | cls.overwrite_input_structure,
29 | ),
30 | cls.results,
31 | )
32 |
33 | spec.expose_outputs(Cp2kCalculation)
34 | spec.output('final_input_parameters', valid_type=orm.Dict, required=False,
35 | help='The input parameters used for the final calculation.')
36 | spec.exit_code(400, 'NO_RESTART_DATA', message="The calculation didn't produce any data to restart from.")
37 | spec.exit_code(300, 'ERROR_UNRECOVERABLE_FAILURE',
38 | message='The calculation failed with an unidentified unrecoverable error.')
39 | spec.exit_code(310, 'ERROR_KNOWN_UNRECOVERABLE_FAILURE',
40 | message='The calculation failed with a known unrecoverable error.')
41 |
42 | def setup(self):
43 | """Call the `setup` of the `BaseRestartWorkChain` and then create the inputs dictionary in `self.ctx.inputs`.
44 |
45 | This `self.ctx.inputs` dictionary will be used by the `BaseRestartWorkChain` to submit the calculations in the
46 | internal loop.
47 | """
48 | super().setup()
49 | self.ctx.inputs = common.AttributeDict(self.exposed_inputs(Cp2kCalculation, 'cp2k'))
50 |
51 | def _collect_all_trajetories(self):
52 | """Collect all trajectories from the children calculations."""
53 | trajectories = []
54 | for called in self.ctx.children:
55 | if isinstance(called, orm.CalcJobNode):
56 | try:
57 | trajectories.append(called.outputs.output_trajectory)
58 | except AttributeError:
59 | pass
60 | return trajectories
61 |
62 | def results(self):
63 | super().results()
64 | if self.inputs.cp2k.parameters != self.ctx.inputs.parameters:
65 | self.out('final_input_parameters', self.ctx.inputs.parameters)
66 |
67 | trajectories = self._collect_all_trajetories()
68 | if trajectories:
69 | self.report("Work chain completed successfully, collecting all trajectories")
70 | if self.ctx.inputs.parameters.get_dict().get("GLOBAL", {}).get("RUN_TYPE") == "GEO_OPT":
71 | output_trajectory = utils.merge_trajectory_data_non_unique(*trajectories)
72 | else:
73 | output_trajectory = utils.merge_trajectory_data_unique(*trajectories)
74 | self.out("output_trajectory", output_trajectory)
75 |
76 | def overwrite_input_structure(self):
77 | if "output_structure" in self.ctx.children[self.ctx.iteration-1].outputs:
78 | self.ctx.inputs.structure = self.ctx.children[self.ctx.iteration-1].outputs.output_structure
79 |
80 | @engine.process_handler(priority=401, exit_codes=[
81 | Cp2kCalculation.exit_codes.ERROR_OUT_OF_WALLTIME,
82 | Cp2kCalculation.exit_codes.ERROR_OUTPUT_INCOMPLETE,
83 | Cp2kCalculation.exit_codes.ERROR_SCF_NOT_CONVERGED,
84 | Cp2kCalculation.exit_codes.ERROR_MAXIMUM_NUMBER_OPTIMIZATION_STEPS_REACHED,
85 | ], enabled=False)
86 | def restart_incomplete_calculation(self, calc):
87 | """This handler restarts incomplete calculations."""
88 | content_string = calc.outputs.retrieved.base.repository.get_object_content(calc.base.attributes.get('output_filename'))
89 |
90 | # CP2K was updating geometry.
91 | possible_geometry_restart = re.search(r"Max. gradient\s+=", content_string) or re.search(r"OPT\| Maximum gradient\s*[-+]?\d*\.?\d+", content_string) or "MD| Step number" in content_string
92 |
93 | # CP2K wrote a wavefunction restart file.
94 | possible_scf_restart = "Total energy: " in content_string
95 |
96 | # External restart file was written.
97 | possible_ext_restart = "Writing RESTART" in content_string
98 |
99 | # Check if calculation aborted due to SCF convergence failure.
100 | scf_didnt_converge_and_aborted = "SCF run NOT converged. To continue the calculation regardless" in content_string
101 | good_scf_gradient = None
102 | if scf_didnt_converge_and_aborted:
103 | scf_gradient = utils.get_last_convergence_value(content_string)
104 | scf_restart_thr = 1e-5 # if ABORT for not SCF convergence, but SCF gradient is small, continue
105 | good_scf_gradient = (scf_gradient is not None) and (scf_gradient < scf_restart_thr)
106 |
107 | # Condition for allowing restart.
108 | restart_possible = any([possible_geometry_restart, possible_scf_restart, possible_ext_restart]) and good_scf_gradient is not False
109 | if not restart_possible: # The message is written in the log file when the CP2K input parameter `LOG_PRINT_KEY` is set to True.
110 | self.report("It seems that the restart of CP2K calculation wouldn't be able to fix the problem as the "
111 | "previous calculation didn't produce any output to restart from. "
112 | "Sending a signal to stop the Base work chain.")
113 |
114 | # Signaling to the base work chain that the problem could not be recovered.
115 | return engine.ProcessHandlerReport(True, self.exit_codes.NO_RESTART_DATA)
116 |
117 | self.ctx.inputs.parent_calc_folder = calc.outputs.remote_folder
118 | params = self.ctx.inputs.parameters
119 |
120 | params = utils.add_wfn_restart_section(params, orm.Bool('kpoints' in self.ctx.inputs))
121 |
122 | if possible_geometry_restart:
123 | # Check if we need to fix restart snapshot in REFTRAJ MD
124 | first_snapshot = None
125 | try:
126 | first_snapshot = int(params['MOTION']['MD']['REFTRAJ']['FIRST_SNAPSHOT']) + calc.outputs.output_trajectory.get_shape('positions')[0]
127 | self.report(f"First snapshot changed from {int(params['MOTION']['MD']['REFTRAJ']['FIRST_SNAPSHOT'])} to {first_snapshot}")
128 | if first_snapshot:
129 | params = utils.add_first_snapshot_in_reftraj_section(params, first_snapshot)
130 | except KeyError:
131 | pass
132 | params = utils.add_ext_restart_section(params)
133 |
134 | is_geo_opt = params.get_dict().get("GLOBAL", {}).get("RUN_TYPE") in ["GEO_OPT", "CELL_OPT"]
135 | if is_geo_opt and good_scf_gradient:
136 | self.report("The SCF was not converged, but the SCF gradient is small and we are optimising geometry. Enabling IGNORE_CONVERGENCE_FAILURE.")
137 | params = utils.add_ignore_convergence_failure(params)
138 |
139 | if calc.exit_code == Cp2kCalculation.exit_codes.ERROR_MAXIMUM_NUMBER_OPTIMIZATION_STEPS_REACHED:
140 | # If the maximum number of optimization steps is reached, we increase the number of steps by 40%.
141 | params = utils.increase_geo_opt_max_iter_by_factor(params, 1.4)
142 |
143 | self.ctx.inputs.parameters = params # params (new or old ones) that include the necessary restart information.
144 | self.report(
145 | "The CP2K calculation wasn't completed. The restart of the calculation might be able to "
146 | "fix the problem.")
147 | return engine.ProcessHandlerReport(False)
148 |
--------------------------------------------------------------------------------
/conftest.py:
--------------------------------------------------------------------------------
1 | """For pytest initialise a test database and profile."""
2 |
3 | import subprocess
4 |
5 | import pytest
6 |
7 | pytest_plugins = ["aiida.manage.tests.pytest_fixtures"]
8 |
9 |
10 | @pytest.fixture(scope="function")
11 | def cp2k_code(aiida_local_code_factory):
12 | return aiida_local_code_factory(
13 | entry_point="cp2k",
14 | executable="/opt/conda/envs/cp2k/bin/cp2k.psmp",
15 | prepend_text='eval "$(command conda shell.bash hook 2> /dev/null)"\nconda activate cp2k\n',
16 | )
17 |
18 |
19 | # from https://stackoverflow.com/a/25188424
20 | # required for examples for optional features to show appropriate error messages
21 | def pytest_configure(config):
22 | import sys
23 |
24 | sys._called_from_test = True
25 |
26 |
27 | def pytest_unconfigure(config):
28 | import sys
29 |
30 | del sys._called_from_test
31 |
32 |
33 | @pytest.fixture(scope="session", autouse=True)
34 | def setup_sssp_pseudos(aiida_profile):
35 | """Create an SSSP pseudo potential family from scratch."""
36 | subprocess.run(
37 | [
38 | "aiida-pseudo",
39 | "install",
40 | "sssp",
41 | "-p",
42 | "efficiency",
43 | "-x",
44 | "PBE",
45 | "-v",
46 | "1.3",
47 | ]
48 | )
49 |
--------------------------------------------------------------------------------
/docs/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | PAPER =
8 | BUILDDIR = build
9 |
10 | # User-friendly check for sphinx-build
11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
13 | endif
14 |
15 | # Internal variables.
16 | PAPEROPT_a4 = -D latex_paper_size=a4
17 | PAPEROPT_letter = -D latex_paper_size=letter
18 | ALLSPHINXOPTS = -n -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
19 | # the i18n builder cannot share the environment and doctrees with the others
20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
21 |
22 | .PHONY: all help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext customdefault
23 |
24 | ## Runs with nitty-pick and converting warnings into errors to
25 | ## make sure the documentation is properly written
26 | customdefault:
27 | $(SPHINXBUILD) -b html -nW $(ALLSPHINXOPTS) $(BUILDDIR)/html
28 |
29 | all: html
30 |
31 | clean:
32 | rm -r $(BUILDDIR)
33 |
34 | html:
35 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
36 | @echo
37 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
38 |
39 |
40 | view:
41 | xdg-open $(BUILDDIR)/html/index.html
42 |
--------------------------------------------------------------------------------
/docs/source/_static/style.css:
--------------------------------------------------------------------------------
1 | .wy-nav-content {
2 | max-width: 800px !important;
3 | }
4 |
--------------------------------------------------------------------------------
/docs/source/_templates/layout.html:
--------------------------------------------------------------------------------
1 | {% extends "!layout.html" %}
2 | {% block extrahead %}
3 |
4 | {% endblock %}
5 |
--------------------------------------------------------------------------------
/docs/source/apidoc/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 |
--------------------------------------------------------------------------------
/docs/source/examples.rst:
--------------------------------------------------------------------------------
1 | Examples
2 | --------
3 |
4 | See `examples` folder for complete examples of setting up a calculation or a work chain.
5 |
6 |
7 | Simple calculation
8 | ==================
9 |
10 | .. code-block:: bash
11 |
12 | cd examples/single_calculations
13 | verdi run example_dft.py # Submit example calculation.
14 | verdi process list -a -p1 # Check status of calculation.
15 |
16 |
17 | Work chain
18 | ==========
19 |
20 | .. code-block:: bash
21 |
22 | cd examples/workchains
23 | verdi run example_base.py # Submit test calculation.
24 | verdi process list -a -p1 # Check status of the work chain.
25 |
--------------------------------------------------------------------------------
/docs/source/features.rst:
--------------------------------------------------------------------------------
1 | Features
2 | --------
3 |
4 | Following the philosophy to ''enable without getting in the way'', this plugin provides access to all of CP2K's capabilities through a small set of well-tested features:
5 |
6 | A full `CP2K input `__ has to be provided as a nested Python dictionary `example `__:
7 |
8 | .. code-block:: python
9 |
10 | params = {'FORCE_EVAL': {'METHOD': 'Quickstep', 'DFT': { ... }}}
11 | builder.parameters = Dict(dict=params)
12 |
13 |
14 | Section parameters are stored as key `_` in the dictionary:
15 |
16 | .. code-block:: python
17 |
18 | xc_section = {'XC_FUNCTIONAL': {'_': 'LDA'}}
19 |
20 | Repeated sections are stored as a list:
21 |
22 | .. code-block:: python
23 |
24 | kind_section = [{'_': 'H', 'BASIS_SET': 'DZVP-MOLOPT-GTH', 'POTENTIAL': 'GTH-LDA'},
25 | {'_': 'O', 'BASIS_SET': 'DZVP-MOLOPT-GTH', 'POTENTIAL': 'GTH-LDA'}]
26 |
27 | Most data files (basis sets, pseudo potentials, VdW, etc.) are auto-discovered from CP2K's `data directory `__.
28 |
29 | .. code-block:: python
30 |
31 | dft_section = {'BASIS_SET_FILE_NAME': 'BASIS_MOLOPT', ...}
32 |
33 |
34 | Additional data files can be added as AiiDA SinglefileData (`example `__):
35 |
36 | .. code-block:: python
37 |
38 | water_pot = SinglefileData(file=os.path.join("/tmp", "water.pot"))
39 | builder.file = {"water_pot": water_pot}
40 |
41 | The start geometry can be provided as AiiDA StructureData (`example `__):
42 |
43 | .. code-block:: python
44 |
45 | structure = StructureData(ase=ase.io.read(os.path.join(thisdir, '..', "files", 'h2o.xyz')))
46 |
47 | Alternatively the start geometry can be contained in the CP2K input (`example `_):
48 |
49 | .. code-block:: python
50 |
51 | 'COORD': {' ': ['H 2.0 2.0 2.737166', 'H 2.0 2.0 2.000000']}
52 |
53 | For restarting a calculation a parent folder can be attached (`example `__):
54 |
55 | .. code-block:: python
56 |
57 | builder.parent_calc_folder = calc1['remote_folder']
58 |
59 | By default only the output and restart file (if present) are retrieved. Additional files are retrieved upon request (`example `__):
60 |
61 | .. code-block:: python
62 |
63 | settings = Dict(dict={'additional_retrieve_list': ["runtime.callgraph"]})
64 | builder.settings = settings
65 |
66 | The final geometry is extracted from the restart file (if present) and stored in AiiDA (`example `__):
67 |
68 | .. code-block:: python
69 |
70 | dist = calc['output_structure'].get_ase().get_distance(0, 1)
71 |
72 |
73 | The conversion of geometries between AiiDA and CP2K has a precision of at least 1e-10 Ångström (`example `__).
74 |
--------------------------------------------------------------------------------
/docs/source/images/AiiDA_transparent_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiidateam/aiida-cp2k/c6b973e774c327066037544cff2e07f80a5fb4a4/docs/source/images/AiiDA_transparent_logo.png
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | .. figure:: images/AiiDA_transparent_logo.png
2 | :width: 250px
3 | :align: center
4 |
5 | The aiida-cp2k plugin for `AiiDA`_
6 | =====================================================
7 |
8 | ``aiida-cp2k`` is available at https://github.com/aiidateam/aiida-cp2k
9 |
10 |
11 | .. toctree::
12 | :maxdepth: 1
13 |
14 | features
15 | examples
16 | workflows
17 |
18 |
19 | API documentation
20 |
21 |
22 | If you use AiiDA for your research, please cite the following work:
23 |
24 | .. highlights:: Giovanni Pizzi, Andrea Cepellotti, Riccardo Sabatini, Nicola Marzari,
25 | and Boris Kozinsky, *AiiDA: automated interactive infrastructure and database
26 | for computational science*, Comp. Mat. Sci 111, 218-230 (2016);
27 | https://doi.org/10.1016/j.commatsci.2015.09.013; http://www.aiida.net.
28 |
29 | ``aiida-cp2k`` is released under the MIT license.
30 |
31 |
32 |
33 |
34 | Indices and tables
35 | ==================
36 |
37 | * :ref:`genindex`
38 | * :ref:`modindex`
39 | * :ref:`search`
40 |
41 | .. _AiiDA: http://www.aiida.net
42 |
--------------------------------------------------------------------------------
/docs/source/workflows.rst:
--------------------------------------------------------------------------------
1 | Workflows
2 | ---------
3 |
4 | .. aiida-workchain:: Cp2kBaseWorkChain
5 | :module: aiida_cp2k.workchains.base
6 |
--------------------------------------------------------------------------------
/examples/files/GTH_POTENTIALS:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | #
3 | # Potential data base file for CP2K (Quickstep)
4 | #
5 | ################################################################################
6 | #
7 | # Pseudopotentials of Goedecker, Teter and Hutter (GTH)
8 | # -----------------------------------------------------
9 | #
10 | # History: - Creation (12.12.1999, Matthias Krack)
11 | # - Electronic configurations added (11.05.2000,MK)
12 | # - GTH-PP for first-row transition metal added (18.03.2003,MK)
13 | # - Automatic update (16.12.2003,MK)
14 | # - PBE GTH-PPs for the Lanthanides added (30.11.2012,MK)
15 | # - Set default GTH PPs (12.08.2016,MK)
16 | # - Last update (21.10.2016,MK)
17 | #
18 | # Literature: - S. Goedecker, M. Teter, and J. Hutter,
19 | # Phys. Rev. B 54, 1703 (1996)
20 | # - C. Hartwigsen, S. Goedecker, and J. Hutter,
21 | # Phys. Rev. B 58, 3641 (1998)
22 | # - M. Krack,
23 | # Theor. Chem. Acc. 114, 145 (2005)
24 | #
25 | # GTH-potential format:
26 | #
27 | # Element symbol Name of the potential Alias names
28 | # n_elec(s) n_elec(p) n_elec(d) ...
29 | # r_loc nexp_ppl cexp_ppl(1) ... cexp_ppl(nexp_ppl)
30 | # nprj
31 | # r(1) nprj_ppnl(1) ((hprj_ppnl(1,i,j),j=i,nprj_ppnl(1)),i=1,nprj_ppnl(1))
32 | # r(2) nprj_ppnl(2) ((hprj_ppnl(2,i,j),j=i,nprj_ppnl(2)),i=1,nprj_ppnl(2))
33 | # . . .
34 | # . . .
35 | # . . .
36 | # r(nprj) nprj_ppnl(nprj) ((hprj_ppnl(nprj,i,j),j=i,nprj_ppnl(nprj)),
37 | # i=1,nprj_ppnl(nprj))
38 | #
39 | # n_elec : Number of electrons for each angular momentum quantum number
40 | # (electronic configuration -> s p d ...)
41 | # r_loc : Radius for the local part defined by the Gaussian function
42 | # exponent alpha_erf
43 | # nexp_ppl : Number of the local pseudopotential functions
44 | # cexp_ppl : Coefficients of the local pseudopotential functions
45 | # nprj : Number of the non-local projectors => nprj = SIZE(nprj_ppnl(:))
46 | # r : Radius of the non-local part for angular momentum quantum number l
47 | # defined by the Gaussian function exponents alpha_prj_ppnl
48 | # nprj_ppnl: Number of the non-local projectors for the angular momentum
49 | # quantum number l
50 | # hprj_ppnl: Coefficients of the non-local projector functions
51 | #
52 | ################################################################################
53 | #
54 | # PADE functional
55 | #
56 | ################################################################################
57 | #
58 | H GTH-PADE-q1 GTH-LDA-q1 GTH-PADE GTH-LDA
59 | 1
60 | 0.20000000 2 -4.18023680 0.72507482
61 | 0
62 | #
63 | He GTH-PADE-q2 GTH-LDA-q2 GTH-PADE GTH-LDA
64 | 2
65 | 0.20000000 2 -9.11202340 1.69836797
66 | 0
67 | #
68 | Li GTH-PADE-q1 GTH-LDA-q1
69 | 1
70 | 0.78755305 2 -1.89261247 0.28605968
71 | 2
72 | 0.66637518 1 1.85881111
73 | 1.07930561 1 -0.00589504
74 | #
75 | Be GTH-PADE-q2 GTH-LDA-q2
76 | 2
77 | 0.73900865 2 -2.59295078 0.35483893
78 | 2
79 | 0.52879656 1 3.06166591
80 | 0.65815348 1 0.09246196
81 | #
82 | B GTH-PADE-q3 GTH-LDA-q3 GTH-PADE GTH-LDA
83 | 2 1
84 | 0.43392956 2 -5.57864173 0.80425145
85 | 2
86 | 0.37384326 1 6.23392822
87 | 0.36039317 0
88 | #
89 | C GTH-PADE-q4 GTH-LDA-q4 GTH-PADE GTH-LDA
90 | 2 2
91 | 0.34883045 2 -8.51377110 1.22843203
92 | 2
93 | 0.30455321 1 9.52284179
94 | 0.23267730 0
95 | #
96 | N GTH-PADE-q5 GTH-LDA-q5 GTH-PADE GTH-LDA
97 | 2 3
98 | 0.28917923 2 -12.23481988 1.76640728
99 | 2
100 | 0.25660487 1 13.55224272
101 | 0.27013369 0
102 | #
103 | O GTH-PADE-q6 GTH-LDA-q6 GTH-PADE GTH-LDA
104 | 2 4
105 | 0.24762086 2 -16.58031797 2.39570092
106 | 2
107 | 0.22178614 1 18.26691718
108 | 0.25682890 0
109 | #
110 | F GTH-PADE-q7 GTH-LDA-q7 GTH-PADE GTH-LDA
111 | 2 5
112 | 0.21852465 2 -21.30736112 3.07286942
113 | 2
114 | 0.19556721 1 23.58494211
115 | 0.17426832 0
116 | #
117 | Ne GTH-PADE-q8 GTH-LDA-q8 GTH-PADE GTH-LDA
118 | 2 6
119 | 0.19000000 2 -27.69285182 4.00590585
120 | 2
121 | 0.17948804 2 28.50609828 0.41682800
122 | -1.07624528
123 | 0.21491271 1 -0.00008991
124 | #
125 | Na GTH-PADE-q1 GTH-LDA-q1
126 | 1
127 | 0.88550938 1 -1.23886713
128 | 2
129 | 0.66110390 2 1.84727135 -0.22540903
130 | 0.58200362
131 | 0.85711928 1 0.47113258
132 | #
133 | Na GTH-PADE-q9 GTH-LDA-q9 GTH-PADE GTH-LDA
134 | 3 6
135 | 0.24631780 2 -7.54559253 1.12599671
136 | 2
137 | 0.14125125 1 36.55698653
138 | 0.13966840 1 -10.39208332
139 | #
140 | Mg GTH-PADE-q10 GTH-LDA-q10 GTH-PADE GTH-LDA
141 | 4 6
142 | 0.21094954 2 -19.41900751 2.87133099
143 | 2
144 | 0.14154696 1 40.31662629
145 | 0.10546902 1 -10.89111329
146 | #
147 | Mg GTH-PADE-q2 GTH-LDA-q2
148 | 2
149 | 0.65181169 1 -2.86429746
150 | 2
151 | 0.55647814 2 2.97095712 -0.51508390
152 | 1.32994091
153 | 0.67756881 1 1.04988101
154 | #
155 | Al GTH-PADE-q3 GTH-LDA-q3 GTH-PADE GTH-LDA
156 | 2 1
157 | 0.45000000 1 -8.49135116
158 | 2
159 | 0.46010427 2 5.08833953 -1.03784325
160 | 2.67969975
161 | 0.53674439 1 2.19343827
162 | #
163 | Si GTH-PADE-q4 GTH-LDA-q4 GTH-PADE GTH-LDA
164 | 2 2
165 | 0.44000000 1 -7.33610297
166 | 2
167 | 0.42273813 2 5.90692831 -1.26189397
168 | 3.25819622
169 | 0.48427842 1 2.72701346
170 | #
171 | P GTH-PADE-q5 GTH-LDA-q5 GTH-PADE GTH-LDA
172 | 2 3
173 | 0.43000000 1 -6.65421981
174 | 2
175 | 0.38980284 2 6.84213556 -1.49369090
176 | 3.85669332
177 | 0.44079585 1 3.28260592
178 | #
179 | S GTH-PADE-q6 GTH-LDA-q6 GTH-PADE GTH-LDA
180 | 2 4
181 | 0.42000000 1 -6.55449184
182 | 2
183 | 0.36175665 2 7.90530250 -1.73188130
184 | 4.47169830
185 | 0.40528502 1 3.86657900
186 | #
187 | Cl GTH-PADE-q7 GTH-LDA-q7 GTH-PADE GTH-LDA
188 | 2 5
189 | 0.41000000 1 -6.86475431
190 | 2
191 | 0.33820832 2 9.06223968 -1.96193036
192 | 5.06568240
193 | 0.37613709 1 4.46587640
194 | #
195 | Ar GTH-PADE-q8 GTH-LDA-q8 GTH-PADE GTH-LDA
196 | 2 6
197 | 0.40000000 1 -7.10000000
198 | 2
199 | 0.31738081 2 10.24948699 -2.16984522
200 | 5.60251627
201 | 0.35161921 1 4.97880101
202 | #
203 | ################################################################################
204 | #
205 | # PBE functional
206 | #
207 | ################################################################################
208 | #
209 | H GTH-PBE-q1 GTH-PBE
210 | 1
211 | 0.20000000 2 -4.17890044 0.72446331
212 | 0
213 | #
214 | He GTH-PBE-q2 GTH-PBE
215 | 2
216 | 0.20000000 2 -9.12214383 1.70270770
217 | 0
218 | #
219 | Li GTH-PBE-q3 GTH-PBE
220 | 3
221 | 0.40000000 4 -14.08115455 9.62621962 -1.78361605 0.08515207
222 | 0
223 | #
224 | Be GTH-PBE-q4 GTH-PBE
225 | 4
226 | 0.32500000 4 -24.06746684 17.27902186 -3.33910629 0.16554912
227 | 0
228 | #
229 | B GTH-PBE-q3 GTH-PBE
230 | 2 1
231 | 0.41899145 2 -5.85946171 0.90375643
232 | 2
233 | 0.37132046 1 6.29728018
234 | 0.36456308 0
235 | #
236 | C GTH-PBE-q4 GTH-PBE
237 | 2 2
238 | 0.33847124 2 -8.80367398 1.33921085
239 | 2
240 | 0.30257575 1 9.62248665
241 | 0.29150694 0
242 | #
243 | N GTH-PBE-q5 GTH-PBE
244 | 2 3
245 | 0.28379051 2 -12.41522559 1.86809592
246 | 2
247 | 0.25540500 1 13.63026257
248 | 0.24549453 0
249 | #
250 | O GTH-PBE-q6 GTH-PBE
251 | 2 4
252 | 0.24455430 2 -16.66721480 2.48731132
253 | 2
254 | 0.22095592 1 18.33745811
255 | 0.21133247 0
256 | #
257 | F GTH-PBE-q7 GTH-PBE
258 | 2 5
259 | 0.21492959 2 -21.57302836 3.19977615
260 | 2
261 | 0.19468402 1 23.74354045
262 | 0.18615608 0
263 | #
264 | Ne GTH-PBE-q8 GTH-PBE
265 | 2 6
266 | 0.19000000 2 -27.12015973 4.36044962
267 | 2
268 | 0.17605938 2 28.17737082 0.83365601
269 | -1.07624528
270 | 0.19547452 1 -0.23629360
271 | #
272 | Na GTH-PBE-q9 GTH-PBE
273 | 3 6
274 | 0.23652322 2 0.29510499 -0.91388488
275 | 2
276 | 0.14356046 1 34.60149228
277 | 0.12993224 1 -14.27746168
278 | #
279 | Mg GTH-PBE-q10 GTH-PBE
280 | 4 6
281 | 0.19275787 2 -20.57539077 3.04016732
282 | 2
283 | 0.14140682 1 41.04729209
284 | 0.10293187 1 -9.98562566
285 | #
286 | Mg GTH-PBE-q2
287 | 2
288 | 0.57696017 1 -2.69040744
289 | 2
290 | 0.59392350 2 3.50321099 -0.71677167
291 | 0.92534825
292 | 0.70715728 1 0.83115848
293 | #
294 | Al GTH-PBE-q3 GTH-PBE
295 | 2 1
296 | 0.45000000 1 -7.55476126
297 | 2
298 | 0.48743529 2 6.95993832 -1.88883584
299 | 2.43847659
300 | 0.56218949 1 1.86529857
301 | #
302 | Si GTH-PBE-q4 GTH-PBE
303 | 2 2
304 | 0.44000000 1 -6.26928833
305 | 2
306 | 0.43563383 2 8.95174150 -2.70627082
307 | 3.49378060
308 | 0.49794218 1 2.43127673
309 | #
310 | P GTH-PBE-q5 GTH-PBE
311 | 2 3
312 | 0.43000000 1 -5.87594327
313 | 2
314 | 0.39637742 2 11.00886207 -3.47035607
315 | 4.48021042
316 | 0.44829838 1 3.05606416
317 | #
318 | S GTH-PBE-q6 GTH-PBE
319 | 2 4
320 | 0.42000000 1 -5.98626038
321 | 2
322 | 0.36482035 2 13.14354448 -4.24183045
323 | 5.47617957
324 | 0.40948048 1 3.70089057
325 | #
326 | Cl GTH-PBE-q7 GTH-PBE
327 | 2 5
328 | 0.41000000 1 -6.39208181
329 | 2
330 | 0.33953864 2 15.21898983 -4.93452321
331 | 6.37044208
332 | 0.37847416 1 4.33877527
333 | #
334 | Ar GTH-PBE-q8 GTH-PBE
335 | 2 6
336 | 0.40000000 1 -7.10000000
337 | 2
338 | 0.31881468 2 17.25203807 -5.58548836
339 | 7.21083447
340 | 0.35337019 1 4.97421551
341 | #
342 |
--------------------------------------------------------------------------------
/examples/files/h2.xyz:
--------------------------------------------------------------------------------
1 | 2
2 | Lattice="4.0 0.0 0.0 0.0 4.0 0.0 0.0 0.0 4.737166" Properties=species:S:1:pos:R:3 pbc="F F F"
3 | H 2.00000000 2.00000000 2.73716600
4 | H 2.00000000 2.00000000 2.00000000
5 |
--------------------------------------------------------------------------------
/examples/files/h2o.xyz:
--------------------------------------------------------------------------------
1 | 3
2 | Lattice="10.0 0.0 0.0 0.0 10.0 0.0 0.0 0.0 10.0" Properties=species:S:1:pos:R:3 pbc="F F F"
3 | O 5.0 5.763239 5.596309
4 | H 5.0 6.526478 5.000000
5 | H 5.0 5.000000 5.000000
6 |
--------------------------------------------------------------------------------
/examples/files/si.xyz:
--------------------------------------------------------------------------------
1 | 2
2 | Lattice="3.81196 0.0 0.0 1.9059800000000005 3.3012541982101284 0.0 1.9059800000000005 1.100418066070043 3.112452306633254" Properties=species:S:1:pos:R:3:_aiidalab_viewer_representation_default:I:1 spacegroup="P 1" unit_cell=conventional pbc="T T T"
3 | Si 0.00000000 0.00000000 0.00000000 0
4 | Si 1.90598000 1.10041807 0.77811308 0
5 |
--------------------------------------------------------------------------------
/examples/gaussian_datatypes/example_automatic.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Simple DFT calculations with Gaussian Datatypes examples"""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run
16 | from aiida.orm import Code, Dict
17 | from aiida.plugins import DataFactory
18 | from gdt_data import load_data
19 |
20 | StructureData = DataFactory("core.structure")
21 |
22 |
23 | def example_gdt(cp2k_code):
24 | """
25 | Testing CP2K with the Basis Set and Pseudopotential stored in gaussian.basisset/pseudo.
26 | In this example the KIND section is omitted completely and the aiida-cp2k plugin will
27 | automatically assign basissets and pseudopotential data based on the different kinds of
28 | the structure. This only works if the assignment can be done unambiguously, hence the
29 | need to give a list of basissets and pseudos to be used. You can also not give more
30 | basissets or pseudos than actually required to avoid false links in the provenance graph.
31 | """
32 |
33 | thisdir = os.path.dirname(os.path.realpath(__file__))
34 |
35 | # Structure.
36 | structure = StructureData(
37 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "h2o.xyz"))
38 | )
39 |
40 | bsets, pseudos = load_data(prefix="MY-AUTO-")
41 | # in your code you will probably use something like:
42 | # bsets = [
43 | # BasisSet.get(element="H", name="DZVP-MOLOPT-GTH")
44 | # BasisSet.get(element="O", name="DZVP-MOLOPT-SR-GTH")
45 | # ]
46 | # ...
47 |
48 | # parameters
49 | parameters = Dict(
50 | {
51 | "FORCE_EVAL": {
52 | "METHOD": "Quickstep",
53 | "DFT": {
54 | "QS": {
55 | "EPS_DEFAULT": 1.0e-12,
56 | "WF_INTERPOLATION": "ps",
57 | "EXTRAPOLATION_ORDER": 3,
58 | },
59 | "MGRID": {"NGRIDS": 4, "CUTOFF": 280, "REL_CUTOFF": 30},
60 | "XC": {"XC_FUNCTIONAL": {"_": "LDA"}},
61 | "POISSON": {"PERIODIC": "none", "PSOLVER": "MT"},
62 | },
63 | }
64 | }
65 | )
66 |
67 | # Construct process builder.
68 | builder = cp2k_code.get_builder()
69 | builder.structure = structure
70 | builder.parameters = parameters
71 | builder.code = cp2k_code
72 | builder.metadata.options.resources = {
73 | "num_machines": 1,
74 | "num_mpiprocs_per_machine": 1,
75 | }
76 | builder.metadata.options.max_wallclock_seconds = 1 * 3 * 60
77 | builder.basissets = bsets
78 | builder.pseudos = pseudos
79 |
80 | print("Submitted calculation...")
81 | run(builder)
82 |
83 |
84 | @click.command("cli")
85 | @click.argument("codelabel")
86 | def cli(codelabel):
87 | """Click interface."""
88 | try:
89 | code = Code.get_from_string(codelabel)
90 | except NotExistent:
91 | print(f"The code '{codelabel}' does not exist.")
92 | sys.exit(1)
93 | example_gdt(code)
94 |
95 |
96 | if __name__ == "__main__":
97 | cli()
98 |
--------------------------------------------------------------------------------
/examples/gaussian_datatypes/example_explicit.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Simple DFT calculations with Gaussian Datatypes examples"""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run
16 | from aiida.orm import Code, Dict
17 | from aiida.plugins import DataFactory
18 | from gdt_data import load_data
19 |
20 | StructureData = DataFactory("core.structure")
21 |
22 |
23 | def example_gdt(cp2k_code):
24 | """
25 | Testing CP2K with the Basis Set and Pseudopotential stored in gaussian.basisset/pseudo.
26 | In this example the names of the basissets and pseudopotentials are still explicitly named
27 | in the CP2K input section. The plugin will then validate the names against the data objects
28 | passed to ensure consistency, and alter the generated CP2K input file to include the parameters
29 | contained in the specified basisset and pseudopotential objects, rather than relying on the
30 | data being present on the target node.
31 | Use this mode if you are migrating from implicitly tracked basissets and pseudos or if you
32 | you have more complicated setups (e.g. having different basissets for the same kind on different sites).
33 | """
34 |
35 | thisdir = os.path.dirname(os.path.realpath(__file__))
36 |
37 | # Structure.
38 | structure = StructureData(
39 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "h2o.xyz"))
40 | )
41 |
42 | # in your actual code you may want to get the basisset and pseudopotential
43 | # with a lookup in the database, here we can simply call load_data()
44 | bsets, pseudos = load_data(prefix="MY-EXPLICIT-")
45 | # in your code you will probably use something like:
46 | # bsets = [
47 | # BasisSet.get(element="H", name="DZVP-MOLOPT-GTH")
48 | # BasisSet.get(element="O", name="DZVP-MOLOPT-SR-GTH")
49 | # ]
50 | # ...
51 |
52 | # parameters
53 | parameters = Dict(
54 | {
55 | "FORCE_EVAL": {
56 | "METHOD": "Quickstep",
57 | "DFT": {
58 | "QS": {
59 | "EPS_DEFAULT": 1.0e-12,
60 | "WF_INTERPOLATION": "ps",
61 | "EXTRAPOLATION_ORDER": 3,
62 | },
63 | "MGRID": {"NGRIDS": 4, "CUTOFF": 280, "REL_CUTOFF": 30},
64 | "XC": {"XC_FUNCTIONAL": {"_": "LDA"}},
65 | "POISSON": {"PERIODIC": "none", "PSOLVER": "MT"},
66 | },
67 | "SUBSYS": {
68 | "KIND": [
69 | {
70 | "_": "O",
71 | "POTENTIAL": "GTH {p.name}".format(p=pseudos["O"]),
72 | "BASIS_SET": "ORB {b.name}".format(b=bsets["O"]),
73 | },
74 | {
75 | "_": "H",
76 | "POTENTIAL": "GTH {p.name}".format(p=pseudos["H"]),
77 | "BASIS_SET": "ORB {b.name}".format(b=bsets["H"]),
78 | },
79 | ]
80 | },
81 | }
82 | }
83 | )
84 |
85 | # Construct process builder.
86 | builder = cp2k_code.get_builder()
87 | builder.structure = structure
88 | builder.parameters = parameters
89 | builder.code = cp2k_code
90 | builder.metadata.options.resources = {
91 | "num_machines": 1,
92 | "num_mpiprocs_per_machine": 1,
93 | }
94 | builder.metadata.options.max_wallclock_seconds = 1 * 3 * 60
95 | builder.basissets = bsets
96 | builder.pseudos = pseudos
97 |
98 | print("Submitted calculation...")
99 | run(builder)
100 |
101 |
102 | @click.command("cli")
103 | @click.argument("codelabel")
104 | def cli(codelabel):
105 | """Click interface."""
106 | try:
107 | code = Code.get_from_string(codelabel)
108 | except NotExistent:
109 | print(f"The code '{codelabel}' does not exist.")
110 | sys.exit(1)
111 | example_gdt(code)
112 |
113 |
114 | if __name__ == "__main__":
115 | cli()
116 |
--------------------------------------------------------------------------------
/examples/gaussian_datatypes/gdt_data.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Create Gaussian basisset and pseudopotential data in the database"""
8 |
9 | from io import StringIO
10 |
11 | from aiida.common.exceptions import UniquenessError
12 | from aiida.plugins import DataFactory
13 |
14 |
15 | def load_data(prefix="MY-"):
16 | """
17 | This is something the user will usually do only ONCE and most likely by
18 | using the CLI of the aiida-gaussian-datatypes.
19 | """
20 |
21 | # Note: the basissets and pseudos deliberately have a prefix to avoid matching
22 | # any CP2K provided entries which may creep in via the DATA_DIR
23 |
24 | bset_input = f"""\
25 | H {prefix}AUTO-DZVP-MOLOPT-GTH {prefix}AUTO-DZVP-MOLOPT-GTH-q1
26 | 1
27 | 2 0 1 7 2 1
28 | 11.478000339908 0.024916243200 -0.012512421400 0.024510918200
29 | 3.700758562763 0.079825490000 -0.056449071100 0.058140794100
30 | 1.446884268432 0.128862675300 0.011242684700 0.444709498500
31 | 0.716814589696 0.379448894600 -0.418587548300 0.646207973100
32 | 0.247918564176 0.324552432600 0.590363216700 0.803385018200
33 | 0.066918004004 0.037148121400 0.438703133000 0.892971208700
34 | 0.021708243634 -0.001125195500 -0.059693171300 0.120101316500
35 |
36 | O {prefix}AUTO-DZVP-MOLOPT-SR-GTH {prefix}AUTO-DZVP-MOLOPT-SR-GTH-q6
37 | 1
38 | 2 0 2 5 2 2 1
39 | 10.389228018317 0.126240722900 0.069215797900 -0.061302037200 -0.026862701100 0.029845227500
40 | 3.849621072005 0.139933704300 0.115634538900 -0.190087511700 -0.006283021000 0.060939733900
41 | 1.388401188741 -0.434348231700 -0.322839719400 -0.377726982800 -0.224839187800 0.732321580100
42 | 0.496955043655 -0.852791790900 -0.095944016600 -0.454266086000 0.380324658600 0.893564918400
43 | 0.162491615040 -0.242351537800 1.102830348700 -0.257388983000 1.054102919900 0.152954188700
44 | """
45 |
46 | pseudo_input = f"""\
47 | #
48 | H {prefix}AUTO-GTH-PADE-q1 {prefix}AUTO-GTH-LDA-q1 {prefix}AUTO-GTH-PADE {prefix}AUTO-GTH-LDA
49 | 1
50 | 0.20000000 2 -4.18023680 0.72507482
51 | 0
52 |
53 | O {prefix}AUTO-GTH-PADE-q6 {prefix}AUTO-GTH-LDA-q6 {prefix}AUTO-GTH-PADE {prefix}AUTO-GTH-LDA
54 | 2 4
55 | 0.24762086 2 -16.58031797 2.39570092
56 | 2
57 | 0.22178614 1 18.26691718
58 | 0.25682890 0
59 | """
60 |
61 | BasisSet = DataFactory("gaussian.basisset")
62 | Pseudo = DataFactory("gaussian.pseudo")
63 |
64 | fhandle_bset = StringIO(bset_input)
65 | fhandle_pseudo = StringIO(pseudo_input)
66 |
67 | try:
68 | bsets = {
69 | b.element: b
70 | for b in BasisSet.from_cp2k(fhandle_bset, duplicate_handling="error")
71 | }
72 | pseudos = {
73 | p.element: p
74 | for p in Pseudo.from_cp2k(fhandle_pseudo, duplicate_handling="error")
75 | }
76 | except (
77 | UniquenessError
78 | ): # if the user already ran the script, fetch the data from the db instead
79 | bsets = {
80 | "H": BasisSet.get("H", f"{prefix}AUTO-DZVP-MOLOPT-GTH"),
81 | "O": BasisSet.get("O", f"{prefix}AUTO-DZVP-MOLOPT-SR-GTH"),
82 | }
83 | pseudos = {
84 | "H": Pseudo.get("H", f"{prefix}AUTO-GTH-PADE-q1"),
85 | "O": Pseudo.get("O", f"{prefix}AUTO-GTH-PADE-q6"),
86 | }
87 |
88 | return bsets, pseudos
89 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_bands.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/cp2k/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Run simple Band Structure calculation"""
8 |
9 | import os
10 | import sys
11 |
12 | import click
13 | import numpy as np
14 | from aiida.common import NotExistent
15 | from aiida.engine import run
16 | from aiida.orm import Dict, SinglefileData, load_code
17 | from aiida.plugins import DataFactory
18 | from ase.atoms import Atoms
19 |
20 | StructureData = DataFactory("core.structure")
21 | KpointsData = DataFactory("core.array.kpoints")
22 |
23 |
24 | def example_bands(cp2k_code):
25 | """Run simple Band Structure calculation"""
26 |
27 | print("Computing Band Structure of Si...")
28 |
29 | thisdir = os.path.dirname(os.path.realpath(__file__))
30 |
31 | # structure
32 | positions = [
33 | [0.0000000000, 0.0000000000, 2.6954627656],
34 | [4.0431941484, 4.0431941484, 4.0431941484],
35 | ]
36 | cell = [
37 | [0.0, 2.69546276561, 2.69546276561],
38 | [2.69546276561, 0.0, 2.69546276561],
39 | [2.69546276561, 2.69546276561, 0.0],
40 | ]
41 | atoms = Atoms("Si2", positions=positions, cell=cell)
42 | structure = StructureData(ase=atoms)
43 |
44 | # kpoints
45 | kpoints_mesh = KpointsData()
46 | kpoints_mesh.set_cell(cell)
47 | kpoints_mesh.set_kpoints_mesh_from_density(distance=0.5)
48 |
49 | # basis set
50 | basis_file = SinglefileData(
51 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
52 | )
53 |
54 | # pseudopotentials
55 | pseudo_file = SinglefileData(
56 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
57 | )
58 |
59 | # parameters
60 | parameters = Dict(
61 | {
62 | "FORCE_EVAL": {
63 | "METHOD": "Quickstep",
64 | "DFT": {
65 | "CHARGE": 0,
66 | "MGRID": {
67 | "CUTOFF": 600,
68 | "NGRIDS": 4,
69 | "REL_CUTOFF": 50,
70 | },
71 | "UKS": False,
72 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
73 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
74 | "QS": {"METHOD": "GPW", "EXTRAPOLATION": "USE_GUESS"},
75 | "POISSON": {
76 | "PERIODIC": "XYZ",
77 | },
78 | "SCF": {
79 | "EPS_SCF": 1.0e-4,
80 | "ADDED_MOS": 1,
81 | "SMEAR": {
82 | "METHOD": "FERMI_DIRAC",
83 | "ELECTRONIC_TEMPERATURE": 300,
84 | },
85 | "DIAGONALIZATION": {"ALGORITHM": "STANDARD", "EPS_ADAPT": 0.01},
86 | "MIXING": {
87 | "METHOD": "BROYDEN_MIXING",
88 | "ALPHA": 0.2,
89 | "BETA": 1.5,
90 | "NBROYDEN": 8,
91 | },
92 | },
93 | "XC": {
94 | "XC_FUNCTIONAL": {
95 | "_": "PBE",
96 | },
97 | },
98 | "PRINT": {
99 | "MO_CUBES": { # this is to print the band gap
100 | "STRIDE": "1 1 1",
101 | "WRITE_CUBE": "F",
102 | "NLUMO": 1,
103 | "NHOMO": 1,
104 | },
105 | "BAND_STRUCTURE": {
106 | "KPOINT_SET": [
107 | {
108 | "NPOINTS": 10,
109 | "SPECIAL_POINT": [
110 | "GAMMA 0.0 0.0 0.0",
111 | "X 0.5 0.0 0.5",
112 | ],
113 | "UNITS": "B_VECTOR",
114 | },
115 | {
116 | "NPOINTS": 10,
117 | "SPECIAL_POINT": [
118 | "X 0.5 0.0 0.5",
119 | "U 0.625 0.25 0.625",
120 | ],
121 | "UNITS": "B_VECTOR",
122 | },
123 | {
124 | "NPOINTS": 10,
125 | "SPECIAL_POINT": [
126 | "K 0.375 0.375 0.75",
127 | "GAMMA 0.0 0.0 0.0",
128 | ],
129 | "UNITS": "B_VECTOR",
130 | },
131 | {
132 | "NPOINTS": 10,
133 | "SPECIAL_POINT": [
134 | "GAMMA 0.0 0.0 0.0",
135 | "L 0.5 0.5 0.5",
136 | ],
137 | "UNITS": "B_VECTOR",
138 | },
139 | {
140 | "NPOINTS": 10,
141 | "SPECIAL_POINT": [
142 | "L 0.5 0.5 0.5",
143 | "W 0.5 0.25 0.75",
144 | ],
145 | "UNITS": "B_VECTOR",
146 | },
147 | {
148 | "NPOINTS": 10,
149 | "SPECIAL_POINT": [
150 | "W 0.5 0.25 0.75",
151 | "X 0.5 0.0 0.5",
152 | ],
153 | "UNITS": "B_VECTOR",
154 | },
155 | ]
156 | },
157 | },
158 | },
159 | "SUBSYS": {
160 | "KIND": [
161 | {
162 | "_": "Si",
163 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
164 | "POTENTIAL": "GTH-LDA-q4",
165 | },
166 | ]
167 | },
168 | "PRINT": { # this is to print forces (may be necessary for problems
169 | # detection)
170 | "FORCES": {
171 | "_": "ON",
172 | }
173 | },
174 | },
175 | "GLOBAL": {
176 | "EXTENDED_FFT_LENGTHS": True, # Needed for large systems
177 | },
178 | }
179 | )
180 |
181 | # Construct process builder
182 | builder = cp2k_code.get_builder()
183 | builder.structure = structure
184 | builder.parameters = parameters
185 | builder.kpoints = kpoints_mesh
186 | builder.code = cp2k_code
187 | builder.file = {
188 | "basis": basis_file,
189 | "pseudo": pseudo_file,
190 | }
191 | builder.metadata.options.resources = {
192 | "num_machines": 1,
193 | "num_mpiprocs_per_machine": 1,
194 | }
195 | builder.metadata.options.max_wallclock_seconds = 1 * 3 * 60
196 |
197 | builder.metadata.options.parser_name = "cp2k_advanced_parser"
198 |
199 | print("submitted calculation...")
200 | calc = run(builder)
201 |
202 | bands = calc["output_bands"]
203 |
204 | # check bands
205 | expected_gamma_kpoint = np.array(
206 | [-6.84282475, 5.23143741, 5.23143741, 5.23143741, 7.89232311]
207 | )
208 |
209 | if bands.get_kpoints().shape == (62, 3):
210 | print("OK, got expected kpoints set size.")
211 | else:
212 | print("Got unexpected kpoints set.")
213 | sys.exit(3)
214 |
215 | if bands.get_bands().shape == (62, 5):
216 | print("OK, got expected bands set size.")
217 | else:
218 | print("Got unexpected bands set.")
219 | sys.exit(3)
220 |
221 | if abs(max(bands.get_bands()[0] - expected_gamma_kpoint)) < 1e-7:
222 | print("Ok, got expected energy levels at GAMMA point.")
223 | else:
224 | print("Got unexpected energy levels at GAMMA point.")
225 | print(bands.get_bands()[0])
226 | print(expected_gamma_kpoint)
227 | sys.exit(3)
228 |
229 |
230 | @click.command("cli")
231 | @click.argument("codelabel")
232 | def cli(codelabel):
233 | """Click interface"""
234 | try:
235 | code = load_code(codelabel)
236 | except NotExistent:
237 | print("The code '{codelabel}' does not exist.")
238 | sys.exit(1)
239 | example_bands(code)
240 |
241 |
242 | if __name__ == "__main__":
243 | cli()
244 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_dft.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Run simple DFT calculation."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run
16 | from aiida.orm import Dict, SinglefileData, load_code
17 | from aiida.plugins import DataFactory
18 |
19 | StructureData = DataFactory("core.structure")
20 |
21 |
22 | def example_dft(cp2k_code):
23 | """Run simple DFT calculation."""
24 |
25 | print("Testing CP2K ENERGY on H2O (DFT)...")
26 |
27 | thisdir = os.path.dirname(os.path.realpath(__file__))
28 |
29 | # Structure.
30 | structure = StructureData(
31 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "h2o.xyz"))
32 | )
33 |
34 | # Basis set.
35 | basis_file = SinglefileData(
36 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
37 | )
38 |
39 | # Pseudopotentials.
40 | pseudo_file = SinglefileData(
41 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
42 | )
43 |
44 | # Parameters.
45 | parameters = Dict(
46 | {
47 | "FORCE_EVAL": {
48 | "METHOD": "Quickstep",
49 | "DFT": {
50 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
51 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
52 | "QS": {
53 | "EPS_DEFAULT": 1.0e-12,
54 | "WF_INTERPOLATION": "ps",
55 | "EXTRAPOLATION_ORDER": 3,
56 | },
57 | "MGRID": {
58 | "NGRIDS": 4,
59 | "CUTOFF": 280,
60 | "REL_CUTOFF": 30,
61 | },
62 | "XC": {
63 | "XC_FUNCTIONAL": {
64 | "_": "LDA",
65 | },
66 | },
67 | "POISSON": {
68 | "PERIODIC": "none",
69 | "PSOLVER": "MT",
70 | },
71 | },
72 | "SUBSYS": {
73 | "KIND": [
74 | {
75 | "_": "O",
76 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
77 | "POTENTIAL": "GTH-LDA-q6",
78 | },
79 | {
80 | "_": "H",
81 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
82 | "POTENTIAL": "GTH-LDA-q1",
83 | },
84 | ],
85 | },
86 | }
87 | }
88 | )
89 |
90 | # Construct process builder.
91 | builder = cp2k_code.get_builder()
92 | builder.structure = structure
93 | builder.parameters = parameters
94 | builder.code = cp2k_code
95 | builder.file = {
96 | "basis": basis_file,
97 | "pseudo": pseudo_file,
98 | }
99 | builder.metadata.options.resources = {
100 | "num_machines": 1,
101 | "num_mpiprocs_per_machine": 1,
102 | }
103 | builder.metadata.options.max_wallclock_seconds = 1 * 3 * 60
104 |
105 | print("Submitted calculation...")
106 | run(builder)
107 |
108 |
109 | @click.command("cli")
110 | @click.argument("codelabel")
111 | def cli(codelabel):
112 | """Click interface."""
113 | try:
114 | code = load_code(codelabel)
115 | except NotExistent:
116 | print(f"The code '{codelabel}' does not exist.")
117 | sys.exit(1)
118 | example_dft(code)
119 |
120 |
121 | if __name__ == "__main__":
122 | cli()
123 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_dft_atomic_kinds.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Run DFT calculation with different atomic kinds."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run
16 | from aiida.orm import Dict, SinglefileData, load_code
17 | from aiida.plugins import DataFactory
18 |
19 | StructureData = DataFactory("core.structure")
20 |
21 |
22 | def example_dft_atomic_kinds(cp2k_code):
23 | """Run DFT calculation with different atomic kinds."""
24 |
25 | print("Testing CP2K GEOP_OPT on Si with different atomic kinds (DFT)...")
26 |
27 | thisdir = os.path.dirname(os.path.realpath(__file__))
28 |
29 | # Structure.
30 | pos = [[0.0, 0.0, 0.0], [1.90598, 1.10041807, 0.77811308]]
31 | cell = [
32 | [3.81196, 0.0, 0.0],
33 | [1.90598, 3.3012541982101, 0.0],
34 | [1.90598, 1.10041806607, 3.1124523066333],
35 | ]
36 | tags = [0, 1]
37 | atoms = ase.Atoms(symbols="Si2", pbc=True, cell=cell, positions=pos, tags=tags)
38 | structure = StructureData(ase=atoms)
39 |
40 | # Basis set.
41 | basis_file = SinglefileData(
42 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
43 | )
44 |
45 | # Pseudopotentials.
46 | pseudo_file = SinglefileData(
47 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
48 | )
49 |
50 | # Parameters.
51 | parameters = Dict(
52 | {
53 | "FORCE_EVAL": {
54 | "METHOD": "Quickstep",
55 | "DFT": {
56 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
57 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
58 | "QS": {
59 | "EPS_DEFAULT": 1.0e-12,
60 | "WF_INTERPOLATION": "ps",
61 | "EXTRAPOLATION_ORDER": 3,
62 | },
63 | "MGRID": {
64 | "NGRIDS": 4,
65 | "CUTOFF": 280,
66 | "REL_CUTOFF": 30,
67 | },
68 | "XC": {
69 | "XC_FUNCTIONAL": {
70 | "_": "LDA",
71 | },
72 | },
73 | "POISSON": {
74 | "PERIODIC": "none",
75 | "PSOLVER": "MT",
76 | },
77 | },
78 | "SUBSYS": {
79 | "KIND": [
80 | {
81 | "_": "Si",
82 | "ELEMENT": "Si",
83 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
84 | "POTENTIAL": "GTH-LDA-q4",
85 | },
86 | {
87 | "_": "Si1",
88 | "ELEMENT": "Si",
89 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
90 | "POTENTIAL": "GTH-LDA-q4",
91 | },
92 | ],
93 | },
94 | },
95 | "MOTION": {
96 | "GEO_OPT": {
97 | "MAX_FORCE": 1e-4,
98 | "MAX_ITER": "3",
99 | "OPTIMIZER": "BFGS",
100 | "BFGS": {
101 | "TRUST_RADIUS": "[bohr] 0.1",
102 | },
103 | },
104 | },
105 | "GLOBAL": {
106 | "RUN_TYPE": "GEO_OPT",
107 | },
108 | }
109 | )
110 |
111 | # Construct process builder.
112 | builder = cp2k_code.get_builder()
113 | builder.structure = structure
114 | builder.parameters = parameters
115 | builder.code = cp2k_code
116 | builder.file = {
117 | "basis": basis_file,
118 | "pseudo": pseudo_file,
119 | }
120 | builder.metadata.options.resources = {
121 | "num_machines": 1,
122 | "num_mpiprocs_per_machine": 1,
123 | }
124 | builder.metadata.options.max_wallclock_seconds = 1 * 3 * 60
125 |
126 | print("Submitted calculation...")
127 | run(builder)
128 |
129 |
130 | @click.command("cli")
131 | @click.argument("codelabel")
132 | def cli(codelabel):
133 | """Click interface."""
134 | try:
135 | code = load_code(codelabel)
136 | except NotExistent:
137 | print(f"The code '{codelabel}' does not exist.")
138 | sys.exit(1)
139 | example_dft_atomic_kinds(code)
140 |
141 |
142 | if __name__ == "__main__":
143 | cli()
144 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_failure.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Run failing calculation."""
8 |
9 | import sys
10 |
11 | import click
12 | from aiida.common import NotExistent
13 | from aiida.engine import run_get_node
14 | from aiida.orm import Dict, load_code
15 |
16 |
17 | def example_failure(cp2k_code):
18 | """Run failing calculation."""
19 |
20 | print("Testing CP2K failure...")
21 |
22 | # a broken CP2K input
23 | parameters = Dict({"GLOBAL": {"FOO_BAR_QUUX": 42}})
24 |
25 | print("Submitted calculation...")
26 |
27 | # Construct process builder
28 | builder = cp2k_code.get_builder()
29 | builder.parameters = parameters
30 | builder.code = cp2k_code
31 | builder.metadata.options.resources = {
32 | "num_machines": 1,
33 | "num_mpiprocs_per_machine": 1,
34 | }
35 | builder.metadata.options.max_wallclock_seconds = 1 * 2 * 60
36 |
37 | _, calc_node = run_get_node(builder)
38 |
39 | if calc_node.exit_status == 304:
40 | print("CP2K failure correctly recognized.")
41 | else:
42 | print("ERROR!")
43 | print("CP2K failure was not recognized.")
44 | sys.exit(3)
45 |
46 |
47 | @click.command("cli")
48 | @click.argument("codelabel")
49 | def cli(codelabel):
50 | """Click interface."""
51 | try:
52 | code = load_code(codelabel)
53 | except NotExistent:
54 | print(f"The code '{codelabel}' does not exist.")
55 | sys.exit(1)
56 | example_failure(code)
57 |
58 |
59 | if __name__ == "__main__":
60 | cli()
61 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_geopt.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Run DFT geometry optimization."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run
16 | from aiida.orm import Dict, SinglefileData, load_code
17 | from aiida.plugins import DataFactory
18 |
19 | StructureData = DataFactory("core.structure")
20 |
21 |
22 | def example_geopt(cp2k_code):
23 | """Run DFT geometry optimization."""
24 |
25 | print("Testing CP2K GEO_OPT on H2O (DFT)...")
26 |
27 | thisdir = os.path.dirname(os.path.realpath(__file__))
28 |
29 | # Structure.
30 | structure = StructureData(
31 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "h2.xyz"))
32 | )
33 |
34 | # Basis set.
35 | basis_file = SinglefileData(
36 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
37 | )
38 |
39 | # Pseudopotentials.
40 | pseudo_file = SinglefileData(
41 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
42 | )
43 |
44 | # Parameters.
45 | parameters = Dict(
46 | {
47 | "GLOBAL": {
48 | "RUN_TYPE": "GEO_OPT",
49 | },
50 | "FORCE_EVAL": {
51 | "METHOD": "Quickstep",
52 | "DFT": {
53 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
54 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
55 | "QS": {
56 | "EPS_DEFAULT": 1.0e-12,
57 | "WF_INTERPOLATION": "ps",
58 | "EXTRAPOLATION_ORDER": 3,
59 | },
60 | "MGRID": {
61 | "NGRIDS": 4,
62 | "CUTOFF": 280,
63 | "REL_CUTOFF": 30,
64 | },
65 | "XC": {
66 | "XC_FUNCTIONAL": {
67 | "_": "PBE",
68 | },
69 | },
70 | "POISSON": {
71 | "PERIODIC": "none",
72 | "PSOLVER": "MT",
73 | },
74 | },
75 | "SUBSYS": {
76 | "KIND": [
77 | {
78 | "_": "O",
79 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
80 | "POTENTIAL": "GTH-PBE-q6",
81 | },
82 | {
83 | "_": "H",
84 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
85 | "POTENTIAL": "GTH-PBE-q1",
86 | },
87 | ],
88 | },
89 | },
90 | }
91 | )
92 |
93 | # Construct process builder.
94 | builder = cp2k_code.get_builder()
95 | builder.structure = structure
96 | builder.parameters = parameters
97 | builder.code = cp2k_code
98 | builder.file = {
99 | "basis": basis_file,
100 | "pseudo": pseudo_file,
101 | }
102 | builder.metadata.options.resources = {
103 | "num_machines": 1,
104 | "num_mpiprocs_per_machine": 1,
105 | }
106 | builder.metadata.options.max_wallclock_seconds = 1 * 3 * 60
107 |
108 | print("Submitted calculation...")
109 | calc = run(builder)
110 |
111 | # Check walltime not exceeded.
112 | assert calc["output_parameters"]["exceeded_walltime"] is False
113 |
114 | # Check energy.
115 | expected_energy = -1.17212345935
116 | if abs(calc["output_parameters"]["energy"] - expected_energy) < 1e-10:
117 | print("OK, energy has the expected value.")
118 | else:
119 | print("ERROR!")
120 | print(f"Expected energy value: {expected_energy}")
121 | print(f"Actual energy value: {calc['output_parameters']['energy']}")
122 | sys.exit(3)
123 |
124 | # Check geometry.
125 | expected_dist = 0.732594809575
126 | dist = calc["output_structure"].get_ase().get_distance(0, 1)
127 | if abs(dist - expected_dist) < 1e-7:
128 | print("OK, H-H distance has the expected value.")
129 | else:
130 | print("ERROR!")
131 | print(f"Expected dist value: {expected_dist}")
132 | print(f"Actual dist value: {dist}")
133 | sys.exit(3)
134 |
135 |
136 | @click.command("cli")
137 | @click.argument("codelabel")
138 | def cli(codelabel):
139 | """Click interface."""
140 | try:
141 | code = load_code(codelabel)
142 | except NotExistent:
143 | print(f"The code '{codelabel}' does not exist.")
144 | sys.exit(1)
145 | example_geopt(code)
146 |
147 |
148 | if __name__ == "__main__":
149 | cli()
150 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_geopt_advanced_parser.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Run DFT geometry optimization."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run
16 | from aiida.orm import Dict, SinglefileData, load_code
17 | from aiida.plugins import DataFactory
18 |
19 | StructureData = DataFactory("core.structure")
20 |
21 |
22 | def example_geopt(cp2k_code):
23 | """Run DFT geometry optimization."""
24 |
25 | print("Testing CP2K GEO_OPT on H2O (DFT)...")
26 |
27 | thisdir = os.path.dirname(os.path.realpath(__file__))
28 |
29 | # Structure.
30 | structure = StructureData(
31 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "h2.xyz"))
32 | )
33 |
34 | # Basis set.
35 | basis_file = SinglefileData(
36 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
37 | )
38 |
39 | # Pseudopotentials.
40 | pseudo_file = SinglefileData(
41 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
42 | )
43 |
44 | # Parameters.
45 | parameters = Dict(
46 | {
47 | "GLOBAL": {
48 | "RUN_TYPE": "GEO_OPT",
49 | },
50 | "FORCE_EVAL": {
51 | "METHOD": "Quickstep",
52 | "DFT": {
53 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
54 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
55 | "QS": {
56 | "EPS_DEFAULT": 1.0e-12,
57 | "WF_INTERPOLATION": "ps",
58 | "EXTRAPOLATION_ORDER": 3,
59 | },
60 | "MGRID": {
61 | "NGRIDS": 4,
62 | "CUTOFF": 280,
63 | "REL_CUTOFF": 30,
64 | },
65 | "XC": {
66 | "XC_FUNCTIONAL": {
67 | "_": "PBE",
68 | },
69 | },
70 | "POISSON": {
71 | "PERIODIC": "none",
72 | "PSOLVER": "MT",
73 | },
74 | },
75 | "SUBSYS": {
76 | "KIND": [
77 | {
78 | "_": "O",
79 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
80 | "POTENTIAL": "GTH-PBE-q6",
81 | },
82 | {
83 | "_": "H",
84 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
85 | "POTENTIAL": "GTH-PBE-q1",
86 | },
87 | ],
88 | },
89 | },
90 | }
91 | )
92 |
93 | # Construct process builder.
94 | builder = cp2k_code.get_builder()
95 | builder.structure = structure
96 | builder.parameters = parameters
97 | builder.code = cp2k_code
98 | builder.file = {
99 | "basis": basis_file,
100 | "pseudo": pseudo_file,
101 | }
102 | builder.metadata.options.resources = {
103 | "num_machines": 1,
104 | "num_mpiprocs_per_machine": 1,
105 | }
106 | builder.metadata.options.max_wallclock_seconds = 1 * 3 * 60
107 | builder.metadata.options.parser_name = "cp2k_advanced_parser"
108 |
109 | print("Submitted calculation...")
110 | calc = run(builder)
111 |
112 | # Check walltime not exceeded.
113 | assert calc["output_parameters"]["exceeded_walltime"] is False
114 |
115 | # Check energy.
116 | expected_energy = -1.17212345935
117 | if abs(calc["output_parameters"]["energy"] - expected_energy) < 1e-10:
118 | print("OK, energy has the expected value.")
119 | else:
120 | print("ERROR!")
121 | print(f"Expected energy value: {expected_energy}")
122 | print(f"Actual energy value: {calc['output_parameters']['energy']}")
123 | sys.exit(3)
124 |
125 | # Check geometry.
126 | expected_dist = 0.732594809575
127 | dist = calc["output_structure"].get_ase().get_distance(0, 1)
128 | if abs(dist - expected_dist) < 1e-7:
129 | print("OK, H-H distance has the expected value.")
130 | else:
131 | print("ERROR!")
132 | print(f"Expected dist value: {expected_dist}")
133 | print(f"Actual dist value: {dist}")
134 | sys.exit(3)
135 |
136 | # Check motion step information.
137 | assert calc["output_parameters"]["motion_step_info"]["step"] == [
138 | 0,
139 | 1,
140 | 2,
141 | ], "ERROR: motion step info is incorrect"
142 | assert calc["output_parameters"]["motion_step_info"]["cell_a_angs"] == [
143 | 4.0,
144 | 4.0,
145 | 4.0,
146 | ], "ERROR: motion step info is incorrect"
147 |
148 |
149 | @click.command("cli")
150 | @click.argument("codelabel")
151 | def cli(codelabel):
152 | """Click interface."""
153 | try:
154 | code = load_code(codelabel)
155 | except NotExistent:
156 | print(f"The code '{codelabel}' does not exist.")
157 | sys.exit(1)
158 | example_geopt(code)
159 |
160 |
161 | if __name__ == "__main__":
162 | cli()
163 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_max_error.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Run simple DFT calculation."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run_get_node
16 | from aiida.orm import Dict, SinglefileData, load_code
17 | from aiida.plugins import CalculationFactory, DataFactory
18 |
19 | StructureData = DataFactory("core.structure")
20 | Cp2kCalculation = CalculationFactory("cp2k")
21 |
22 |
23 | def example_dft(cp2k_code):
24 | """Run simple DFT calculation."""
25 |
26 | print("Testing CP2K GEO_OPT ERROR MAX on H2O (DFT)...")
27 |
28 | thisdir = os.path.dirname(os.path.realpath(__file__))
29 |
30 | # Structure.
31 | structure = StructureData(
32 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "h2o.xyz"))
33 | )
34 |
35 | # Basis set.
36 | basis_file = SinglefileData(
37 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
38 | )
39 |
40 | # Pseudopotentials.
41 | pseudo_file = SinglefileData(
42 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
43 | )
44 |
45 | # Parameters.
46 | parameters = Dict(
47 | {
48 | "GLOBAL": {
49 | "RUN_TYPE": "GEO_OPT",
50 | },
51 | "MOTION": {
52 | "GEO_OPT": {
53 | "OPTIMIZER": "BFGS",
54 | "MAX_ITER": "2",
55 | "MAX_DR": 0.0001,
56 | "RMS_DR": 0.00005,
57 | "MAX_FORCE": 0.000015,
58 | "RMS_FORCE": 0.00001,
59 | },
60 | },
61 | "FORCE_EVAL": {
62 | "METHOD": "Quickstep",
63 | "DFT": {
64 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
65 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
66 | "QS": {"EPS_DEFAULT": 1.0e-8, "EXTRAPOLATION": "use_prev_p"},
67 | "MGRID": {
68 | "NGRIDS": 4,
69 | "CUTOFF": 200,
70 | "REL_CUTOFF": 30,
71 | },
72 | "XC": {
73 | "XC_FUNCTIONAL": {
74 | "_": "LDA",
75 | },
76 | },
77 | "POISSON": {
78 | "PERIODIC": "none",
79 | "PSOLVER": "MT",
80 | },
81 | },
82 | "SUBSYS": {
83 | "KIND": [
84 | {
85 | "_": "O",
86 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
87 | "POTENTIAL": "GTH-LDA-q6",
88 | },
89 | {
90 | "_": "H",
91 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
92 | "POTENTIAL": "GTH-LDA-q1",
93 | },
94 | ],
95 | },
96 | },
97 | }
98 | )
99 |
100 | # Construct process builder.
101 | builder = cp2k_code.get_builder()
102 | builder.structure = structure
103 | builder.parameters = parameters
104 | builder.code = cp2k_code
105 | builder.file = {
106 | "basis": basis_file,
107 | "pseudo": pseudo_file,
108 | }
109 | builder.metadata.options.resources = {
110 | "num_machines": 1,
111 | "num_mpiprocs_per_machine": 1,
112 | }
113 | builder.metadata.options.max_wallclock_seconds = 1 * 3 * 60
114 |
115 | print("Submitted calculation...")
116 | calc = run_get_node(builder)
117 | assert (
118 | calc[1].exit_status
119 | == Cp2kCalculation.exit_codes.ERROR_MAXIMUM_NUMBER_OPTIMIZATION_STEPS_REACHED.status
120 | )
121 |
122 |
123 | @click.command("cli")
124 | @click.argument("codelabel")
125 | def cli(codelabel):
126 | """Click interface."""
127 | try:
128 | code = load_code(codelabel)
129 | except NotExistent:
130 | print(f"The code '{codelabel}' does not exist.")
131 | sys.exit(1)
132 | example_dft(code)
133 |
134 |
135 | if __name__ == "__main__":
136 | cli()
137 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_mm.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Run molecular mechanics calculation."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run
16 | from aiida.orm import Dict, SinglefileData, load_code
17 |
18 |
19 | def example_mm(cp2k_code):
20 | """Run molecular mechanics calculation."""
21 |
22 | print("Testing CP2K ENERGY on H2O (MM) ...")
23 |
24 | # Force field.
25 | with open(os.path.join("/tmp", "water.pot"), "w") as f:
26 | f.write(
27 | """BONDS
28 | H H 0.000 1.5139
29 | O H 450.000 0.9572
30 |
31 | ANGLES
32 | H O H 55.000 104.5200
33 |
34 | DIHEDRALS
35 |
36 | IMPROPER
37 |
38 | NONBONDED
39 | H 0.000000 -0.046000 0.224500
40 | O 0.000000 -0.152100 1.768200
41 |
42 | HBOND CUTHB 0.5
43 |
44 | END"""
45 | )
46 |
47 | water_pot = SinglefileData(file=os.path.join("/tmp", "water.pot"))
48 |
49 | thisdir = os.path.dirname(os.path.realpath(__file__))
50 |
51 | # structure using pdb format, because it also carries topology information
52 | atoms = ase.io.read(os.path.join(thisdir, "..", "files", "h2o.xyz"))
53 | atoms.center(vacuum=10.0)
54 | atoms.write(os.path.join("/tmp", "coords.pdb"), format="proteindatabank")
55 | coords_pdb = SinglefileData(file=os.path.join("/tmp", "coords.pdb"))
56 |
57 | # Parameters.
58 | # Based on cp2k/tests/Fist/regtest-1-1/water_1.inp
59 | parameters = Dict(
60 | {
61 | "FORCE_EVAL": {
62 | "METHOD": "fist",
63 | "MM": {
64 | "FORCEFIELD": {
65 | "PARM_FILE_NAME": "water.pot",
66 | "PARMTYPE": "CHM",
67 | "CHARGE": [
68 | {"ATOM": "O", "CHARGE": -0.8476},
69 | {"ATOM": "H", "CHARGE": 0.4238},
70 | ],
71 | },
72 | "POISSON": {
73 | "EWALD": {
74 | "EWALD_TYPE": "spme",
75 | "ALPHA": 0.44,
76 | "GMAX": 24,
77 | "O_SPLINE": 6,
78 | }
79 | },
80 | },
81 | "SUBSYS": {
82 | "CELL": {
83 | "ABC": "%f %f %f" % tuple(atoms.cell.diagonal()),
84 | },
85 | "TOPOLOGY": {
86 | "COORD_FILE_NAME": "coords.pdb",
87 | "COORD_FILE_FORMAT": "PDB",
88 | },
89 | },
90 | },
91 | "GLOBAL": {"CALLGRAPH": "master", "CALLGRAPH_FILE_NAME": "runtime"},
92 | }
93 | )
94 |
95 | # Settings.
96 | settings = Dict({"additional_retrieve_list": ["runtime.callgraph"]})
97 |
98 | # Construct process builder.
99 | builder = cp2k_code.get_builder()
100 | builder.parameters = parameters
101 | builder.settings = settings
102 | builder.code = cp2k_code
103 | builder.file = {
104 | "water_pot": water_pot,
105 | "coords_pdb": coords_pdb,
106 | }
107 | builder.metadata.options.resources = {
108 | "num_machines": 1,
109 | "num_mpiprocs_per_machine": 1,
110 | }
111 | builder.metadata.options.max_wallclock_seconds = 1 * 3 * 60
112 |
113 | print("Submitted calculation...")
114 | calc = run(builder)
115 |
116 | # Check energy.
117 | expected_energy = 0.146927412614e-3
118 | if abs(calc["output_parameters"]["energy"] - expected_energy) < 1e-10:
119 | print("OK, energy has the expected value.")
120 | else:
121 | print("ERROR!")
122 | print(f"Expected energy value: {expected_energy}")
123 | print(f"Actual energy value: {calc['output_parameters']['energy']}")
124 | sys.exit(3)
125 |
126 | # Check if callgraph is there.
127 | if "runtime.callgraph" in calc["retrieved"].base.repository.list_object_names():
128 | print("OK, callgraph file was retrived.")
129 | else:
130 | print("ERROR!")
131 | print("Callgraph file was not retrieved.")
132 | sys.exit(3)
133 |
134 |
135 | @click.command("cli")
136 | @click.argument("codelabel")
137 | def cli(codelabel):
138 | """Click interface."""
139 | try:
140 | code = load_code(codelabel)
141 | except NotExistent:
142 | print(f"The code '{codelabel}' does not exist.")
143 | sys.exit(1)
144 | example_mm(code)
145 |
146 |
147 | if __name__ == "__main__":
148 | cli()
149 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_mm_md.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Run molecular dynamics calculation."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida import common, engine, orm
15 |
16 |
17 | def example_mm(cp2k_code):
18 | """Run molecular mechanics calculation."""
19 |
20 | print("Testing CP2K ENERGY on H2O (MM) ...")
21 |
22 | # Force field.
23 | with open(os.path.join("/tmp", "water.pot"), "w") as f:
24 | f.write(
25 | """BONDS
26 | H H 0.000 1.5139
27 | O H 450.000 0.9572
28 |
29 | ANGLES
30 | H O H 55.000 104.5200
31 |
32 | DIHEDRALS
33 |
34 | IMPROPER
35 |
36 | NONBONDED
37 | H 0.000000 -0.046000 0.224500
38 | O 0.000000 -0.152100 1.768200
39 |
40 | HBOND CUTHB 0.5
41 |
42 | END"""
43 | )
44 |
45 | water_pot = orm.SinglefileData(file=os.path.join("/tmp", "water.pot"))
46 |
47 | thisdir = os.path.dirname(os.path.realpath(__file__))
48 |
49 | # structure using pdb format, because it also carries topology information
50 | atoms = ase.io.read(os.path.join(thisdir, "..", "files", "h2o.xyz"))
51 | atoms.center(vacuum=10.0)
52 | atoms.write(os.path.join("/tmp", "coords.pdb"), format="proteindatabank")
53 | coords_pdb = orm.SinglefileData(file=os.path.join("/tmp", "coords.pdb"))
54 |
55 | # Parameters.
56 | # Based on cp2k/tests/Fist/regtest-1-1/water_1.inp
57 | parameters = orm.Dict(
58 | {
59 | "FORCE_EVAL": {
60 | "METHOD": "fist",
61 | "STRESS_TENSOR": "analytical",
62 | "MM": {
63 | "FORCEFIELD": {
64 | "PARM_FILE_NAME": "water.pot",
65 | "PARMTYPE": "CHM",
66 | "CHARGE": [
67 | {"ATOM": "O", "CHARGE": -0.8476},
68 | {"ATOM": "H", "CHARGE": 0.4238},
69 | ],
70 | },
71 | "POISSON": {
72 | "EWALD": {
73 | "EWALD_TYPE": "spme",
74 | "ALPHA": 0.44,
75 | "GMAX": 24,
76 | "O_SPLINE": 6,
77 | }
78 | },
79 | },
80 | "SUBSYS": {
81 | "CELL": {
82 | "ABC": "%f %f %f" % tuple(atoms.cell.diagonal()),
83 | },
84 | "TOPOLOGY": {
85 | "COORD_FILE_NAME": "coords.pdb",
86 | "COORD_FILE_FORMAT": "PDB",
87 | },
88 | },
89 | },
90 | "MOTION": {
91 | "CONSTRAINT": {},
92 | "MD": {
93 | "THERMOSTAT": {"CSVR": {}, "TYPE": "csvr"},
94 | "BAROSTAT": {},
95 | "STEPS": 1000,
96 | "ENSEMBLE": "npt_f",
97 | "TEMPERATURE": 300.0,
98 | },
99 | "PRINT": {
100 | "TRAJECTORY": {"EACH": {"MD": 5}},
101 | "RESTART": {"EACH": {"MD": 5}},
102 | "RESTART_HISTORY": {"_": "OFF"},
103 | "CELL": {"EACH": {"MD": 5}},
104 | "FORCES": {"EACH": {"MD": 5}, "FORMAT": "XYZ"},
105 | },
106 | },
107 | "GLOBAL": {
108 | "CALLGRAPH": "master",
109 | "CALLGRAPH_FILE_NAME": "runtime",
110 | "PRINT_LEVEL": "medium",
111 | "RUN_TYPE": "MD",
112 | },
113 | }
114 | )
115 |
116 | # Construct process builder.
117 | builder = cp2k_code.get_builder()
118 | builder.parameters = parameters
119 | builder.code = cp2k_code
120 | builder.file = {
121 | "water_pot": water_pot,
122 | "coords_pdb": coords_pdb,
123 | }
124 | builder.metadata.options.resources = {
125 | "num_machines": 1,
126 | "num_mpiprocs_per_machine": 1,
127 | }
128 | builder.metadata.options.max_wallclock_seconds = 1 * 3 * 60
129 |
130 | print("Submitted calculation...")
131 | results = engine.run(builder)
132 | assert "output_trajectory" in results, "Output trajectory not found among results."
133 | traj = results["output_trajectory"]
134 |
135 | assert traj.get_cells().shape == (201, 3, 3), "Unexpected shape of cells."
136 | assert traj.get_positions().shape == (201, 3, 3), "Unexpected shape of positions."
137 | assert traj.get_array("forces").shape == (201, 3, 3), "Unexpected shape of forces."
138 |
139 |
140 | @click.command("cli")
141 | @click.argument("codelabel")
142 | def cli(codelabel):
143 | """Click interface."""
144 | try:
145 | code = orm.load_code(codelabel)
146 | except common.NotExistent:
147 | print(f"The code '{codelabel}' does not exist.")
148 | sys.exit(1)
149 | example_mm(code)
150 |
151 |
152 | if __name__ == "__main__":
153 | cli()
154 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_multiple_force_eval.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Run DFT calculation with multiple force eval sections."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run
16 | from aiida.orm import Dict, SinglefileData, load_code
17 | from aiida.plugins import DataFactory
18 |
19 | StructureData = DataFactory("core.structure")
20 |
21 |
22 | def example_multiple_force_eval(cp2k_code):
23 | """Run DFT calculation with multiple force eval sections."""
24 |
25 | print("Testing CP2K ENERGY on H2O dimer (Mixed: DFT+MM)...")
26 |
27 | thisdir = os.path.dirname(os.path.realpath(__file__))
28 |
29 | # structure
30 | pos = [
31 | [0.934, 2.445, 1.844],
32 | [1.882, 2.227, 1.982],
33 | [0.81, 3.165, 2.479],
34 | [3.59, 2.048, 2.436],
35 | [4.352, 2.339, 1.906],
36 | [3.953, 1.304, 2.946],
37 | ]
38 | atoms = ase.Atoms(symbols="OH2OH2", pbc=True, cell=[5.0, 5.0, 5.0])
39 | atoms.set_positions(pos)
40 | structure = StructureData(ase=atoms)
41 |
42 | # Basis set.
43 | basis_file = SinglefileData(
44 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
45 | )
46 |
47 | # Pseudopotentials.
48 | pseudo_file = SinglefileData(
49 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
50 | )
51 |
52 | # Parameters.
53 | parameters = Dict(
54 | {
55 | "MULTIPLE_FORCE_EVALS": {
56 | "FORCE_EVAL_ORDER": "2 3",
57 | "MULTIPLE_SUBSYS": "T",
58 | },
59 | "FORCE_EVAL": [
60 | {
61 | "METHOD": "MIXED",
62 | "MIXED": {
63 | "MIXING_TYPE": "GENMIX",
64 | "GENERIC": {
65 | "ERROR_LIMIT": 1.0e-10,
66 | "MIXING_FUNCTION": "E1+E2",
67 | "VARIABLES": "E1 E2",
68 | },
69 | "MAPPING": {
70 | "FORCE_EVAL_MIXED": {
71 | "FRAGMENT": [
72 | {"_": 1, "1": "3"},
73 | {"_": 2, "4": "6"},
74 | ],
75 | },
76 | "FORCE_EVAL": [
77 | {
78 | "_": 1,
79 | "DEFINE_FRAGMENTS": "1 2",
80 | },
81 | {
82 | "_": 2,
83 | "DEFINE_FRAGMENTS": "1 2",
84 | },
85 | ],
86 | },
87 | },
88 | },
89 | {
90 | "METHOD": "FIST",
91 | "MM": {
92 | "FORCEFIELD": {
93 | "SPLINE": {
94 | "EPS_SPLINE": 1.30e-5,
95 | "EMAX_SPLINE": 0.8,
96 | },
97 | "CHARGE": [
98 | {
99 | "ATOM": "H",
100 | "CHARGE": 0.0,
101 | },
102 | {
103 | "ATOM": "O",
104 | "CHARGE": 0.0,
105 | },
106 | ],
107 | "BOND": {
108 | "ATOMS": "H O",
109 | "K": 0.0,
110 | "R0": 2.0,
111 | },
112 | "BEND": {
113 | "ATOMS": "H O H",
114 | "K": 0.0,
115 | "THETA0": 2.0,
116 | },
117 | "NONBONDED": {
118 | "LENNARD-JONES": [
119 | {
120 | "ATOMS": "H H",
121 | "EPSILON": 0.2,
122 | "SIGMA": 2.4,
123 | },
124 | {
125 | "ATOMS": "H O",
126 | "EPSILON": 0.4,
127 | "SIGMA": 3.0,
128 | },
129 | {
130 | "ATOMS": "O O",
131 | "EPSILON": 0.8,
132 | "SIGMA": 3.6,
133 | },
134 | ]
135 | },
136 | },
137 | "POISSON": {
138 | "EWALD": {
139 | "EWALD_TYPE": "none",
140 | }
141 | },
142 | },
143 | "SUBSYS": {
144 | "TOPOLOGY": {
145 | "CONNECTIVITY": "GENERATE",
146 | "GENERATE": {
147 | "CREATE_MOLECULES": True,
148 | },
149 | }
150 | },
151 | },
152 | {
153 | "METHOD": "Quickstep",
154 | "DFT": {
155 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
156 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
157 | "QS": {
158 | "EPS_DEFAULT": 1.0e-12,
159 | "WF_INTERPOLATION": "ps",
160 | "EXTRAPOLATION_ORDER": 3,
161 | },
162 | "MGRID": {
163 | "NGRIDS": 4,
164 | "CUTOFF": 280,
165 | "REL_CUTOFF": 30,
166 | },
167 | "XC": {
168 | "XC_FUNCTIONAL": {
169 | "_": "LDA",
170 | },
171 | },
172 | "POISSON": {
173 | "PERIODIC": "none",
174 | "PSOLVER": "MT",
175 | },
176 | },
177 | "SUBSYS": {
178 | "KIND": [
179 | {
180 | "_": "O",
181 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
182 | "POTENTIAL": "GTH-LDA-q6",
183 | },
184 | {
185 | "_": "H",
186 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
187 | "POTENTIAL": "GTH-LDA-q1",
188 | },
189 | ],
190 | },
191 | },
192 | ],
193 | }
194 | )
195 |
196 | # Construct process builder.
197 | builder = cp2k_code.get_builder()
198 | builder.structure = structure
199 | builder.parameters = parameters
200 | builder.code = cp2k_code
201 | builder.file = {
202 | "basis": basis_file,
203 | "pseudo": pseudo_file,
204 | }
205 | builder.metadata.options.resources = {
206 | "num_machines": 1,
207 | "num_mpiprocs_per_machine": 1,
208 | }
209 | builder.metadata.options.max_wallclock_seconds = 1 * 3 * 60
210 |
211 | print("Submitted calculation...")
212 | run(builder)
213 |
214 |
215 | @click.command("cli")
216 | @click.argument("codelabel")
217 | def cli(codelabel):
218 | """Click interface."""
219 | try:
220 | code = load_code(codelabel)
221 | except NotExistent:
222 | print(f"The code '{codelabel}' does not exist.")
223 | sys.exit(1)
224 | example_multiple_force_eval(code)
225 |
226 |
227 | if __name__ == "__main__":
228 | cli()
229 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_no_struct.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Run DFT calculation with structure specified in the input file."""
8 |
9 | import os
10 | import sys
11 |
12 | import click
13 | from aiida.common import NotExistent
14 | from aiida.engine import run
15 | from aiida.orm import Dict, SinglefileData, load_code
16 |
17 |
18 | def example_no_struct(cp2k_code):
19 | """Run DFT calculation with structure specified in the input file."""
20 |
21 | print("Testing CP2K ENERGY on H2 (DFT) without StructureData...")
22 |
23 | thisdir = os.path.dirname(os.path.realpath(__file__))
24 |
25 | # Basis set.
26 | basis_file = SinglefileData(
27 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
28 | )
29 |
30 | # Pseudopotentials.
31 | pseudo_file = SinglefileData(
32 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
33 | )
34 |
35 | # Parameters.
36 | parameters = Dict(
37 | {
38 | "FORCE_EVAL": {
39 | "METHOD": "Quickstep",
40 | "DFT": {
41 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
42 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
43 | "QS": {
44 | "EPS_DEFAULT": 1.0e-12,
45 | "WF_INTERPOLATION": "ps",
46 | "EXTRAPOLATION_ORDER": 3,
47 | },
48 | "MGRID": {
49 | "NGRIDS": 4,
50 | "CUTOFF": 280,
51 | "REL_CUTOFF": 30,
52 | },
53 | "XC": {
54 | "XC_FUNCTIONAL": {
55 | "_": "LDA",
56 | },
57 | },
58 | "POISSON": {
59 | "PERIODIC": "none",
60 | "PSOLVER": "MT",
61 | },
62 | },
63 | "SUBSYS": {
64 | # structure directly included in parameters
65 | "CELL": {"ABC": "4.0 4.0 4.75"},
66 | "COORD": {
67 | " ": ["H 2.0 2.0 2.737166", "H 2.0 2.0 2.000000"]
68 | },
69 | "KIND": [
70 | {
71 | "_": "O",
72 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
73 | "POTENTIAL": "GTH-LDA-q6",
74 | },
75 | {
76 | "_": "H",
77 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
78 | "POTENTIAL": "GTH-LDA-q1",
79 | },
80 | ],
81 | },
82 | }
83 | }
84 | )
85 |
86 | # Construct process builder.
87 | builder = cp2k_code.get_builder()
88 | builder.parameters = parameters
89 | builder.code = cp2k_code
90 | builder.file = {
91 | "basis": basis_file,
92 | "pseudo": pseudo_file,
93 | }
94 | builder.metadata.options.resources = {
95 | "num_machines": 1,
96 | "num_mpiprocs_per_machine": 1,
97 | }
98 | builder.metadata.options.max_wallclock_seconds = 1 * 3 * 60
99 |
100 | print("Submitted calculation...")
101 | calc = run(builder)
102 |
103 | # Check energy.
104 | expected_energy = -1.14005678487
105 | if abs(calc["output_parameters"]["energy"] - expected_energy) < 1e-10:
106 | print("OK, energy has the expected value.")
107 | else:
108 | print("ERROR!")
109 | print(f"Expected energy value: {expected_energy}")
110 | print(f"Actual energy value: {calc['output_parameters']['energy']}")
111 | sys.exit(3)
112 |
113 |
114 | @click.command("cli")
115 | @click.argument("codelabel")
116 | def cli(codelabel):
117 | """Click interface."""
118 | try:
119 | code = load_code(codelabel)
120 | except NotExistent:
121 | print(f"The code '{codelabel}' does not exist.")
122 | sys.exit(1)
123 | example_no_struct(code)
124 |
125 |
126 | if __name__ == "__main__":
127 | cli()
128 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_precision.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Test structure roundtrip precision ase->aiida->cp2k->aiida->ase."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase
13 | import click
14 | import numpy as np
15 | from aiida.common import NotExistent
16 | from aiida.engine import run
17 | from aiida.orm import Dict, SinglefileData, load_code
18 | from aiida.plugins import DataFactory
19 |
20 | StructureData = DataFactory("core.structure")
21 |
22 |
23 | def example_precision(cp2k_code):
24 | """Test structure roundtrip precision ase->aiida->cp2k->aiida->ase."""
25 |
26 | print("Testing structure roundtrip precision ase->aiida->cp2k->aiida->ase...")
27 |
28 | thisdir = os.path.dirname(os.path.realpath(__file__))
29 |
30 | # Structure.
31 | epsilon = 1e-10 # expected precision in Angstrom
32 | dist = 0.74 + epsilon
33 | positions = [(0, 0, 0), (0, 0, dist)]
34 | cell = np.diag([4, -4, 4 + epsilon])
35 | atoms = ase.Atoms("H2", positions=positions, cell=cell)
36 | structure = StructureData(ase=atoms)
37 |
38 | # Basis set.
39 | basis_file = SinglefileData(
40 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
41 | )
42 |
43 | # Pseudopotentials.
44 | pseudo_file = SinglefileData(
45 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
46 | )
47 |
48 | # Parameters.
49 | parameters = Dict(
50 | {
51 | "GLOBAL": {
52 | "RUN_TYPE": "MD",
53 | },
54 | "MOTION": {
55 | "MD": {
56 | "TIMESTEP": 0.0, # do not move atoms
57 | "STEPS": 1,
58 | },
59 | },
60 | "FORCE_EVAL": {
61 | "METHOD": "Quickstep",
62 | "DFT": {
63 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
64 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
65 | "SCF": {
66 | "MAX_SCF": 10,
67 | },
68 | "XC": {
69 | "XC_FUNCTIONAL": {
70 | "_": "LDA",
71 | },
72 | },
73 | },
74 | "SUBSYS": {
75 | "KIND": {
76 | "_": "DEFAULT",
77 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
78 | "POTENTIAL": "GTH-LDA",
79 | },
80 | },
81 | },
82 | }
83 | )
84 |
85 | # Construct process builder.
86 | builder = cp2k_code.get_builder()
87 | builder.structure = structure
88 | builder.parameters = parameters
89 | builder.code = cp2k_code
90 | builder.file = {
91 | "basis": basis_file,
92 | "pseudo": pseudo_file,
93 | }
94 | builder.metadata.options.resources = {
95 | "num_machines": 1,
96 | "num_mpiprocs_per_machine": 1,
97 | }
98 | builder.metadata.options.max_wallclock_seconds = 1 * 60 * 60
99 |
100 | print("Submitted calculation...")
101 | calc = run(builder)
102 |
103 | # Check structure preservation.
104 | atoms2 = calc["output_structure"].get_ase()
105 |
106 | # Zeros should be preserved exactly.
107 | if np.all(atoms2.positions[0] == 0.0):
108 | print("OK, zeros in structure were preserved exactly.")
109 | else:
110 | print("ERROR!")
111 | print("Zeros in structure changed: ", atoms2.positions[0])
112 | sys.exit(3)
113 |
114 | # Other values should be preserved with epsilon precision.
115 | dist2 = atoms2.get_distance(0, 1)
116 | if abs(dist2 - dist) < epsilon:
117 | print("OK, structure preserved with %.1e Angstrom precision" % epsilon)
118 | else:
119 | print("ERROR!")
120 | print("Structure changed by %e Angstrom" % abs(dist - dist2))
121 | sys.exit(3)
122 |
123 | # Check cell preservation.
124 | cell_diff = np.amax(np.abs(atoms2.cell - cell))
125 | if cell_diff < epsilon:
126 | print("OK, cell preserved with %.1e Angstrom precision" % epsilon)
127 | else:
128 | print("ERROR!")
129 | print("Cell changed by %e Angstrom" % cell_diff)
130 | sys.exit(3)
131 |
132 |
133 | @click.command("cli")
134 | @click.argument("codelabel")
135 | def cli(codelabel):
136 | """Click interface."""
137 | try:
138 | code = load_code(codelabel)
139 | except NotExistent:
140 | print("The code '{codelabel}' does not exist.")
141 | sys.exit(1)
142 | example_precision(code)
143 |
144 |
145 | if __name__ == "__main__":
146 | cli()
147 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_restart.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Test CP2K restart."""
8 |
9 | import os
10 | import re
11 | import sys
12 | from copy import deepcopy
13 |
14 | import ase.io
15 | import click
16 | from aiida import common, engine, orm, plugins
17 |
18 | StructureData = plugins.DataFactory("core.structure")
19 |
20 |
21 | def example_restart(cp2k_code):
22 | """Test CP2K restart."""
23 |
24 | print("Testing CP2K restart...")
25 |
26 | thisdir = os.path.dirname(os.path.realpath(__file__))
27 |
28 | # Structure.
29 | structure = StructureData(
30 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "h2o.xyz"))
31 | )
32 |
33 | # Basis set.
34 | basis_file = orm.SinglefileData(
35 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
36 | )
37 |
38 | # Pseudopotentials.
39 | pseudo_file = orm.SinglefileData(
40 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
41 | )
42 |
43 | # CP2K input.
44 | params1 = orm.Dict(
45 | {
46 | "GLOBAL": {
47 | "RUN_TYPE": "GEO_OPT",
48 | "WALLTIME": "00:00:20", # too short
49 | },
50 | "MOTION": {
51 | "GEO_OPT": {
52 | "MAX_FORCE": 1e-20, # impossible to reach
53 | "MAX_ITER": 100000, # run forever
54 | },
55 | },
56 | "FORCE_EVAL": {
57 | "METHOD": "Quickstep",
58 | "DFT": {
59 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
60 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
61 | "QS": {
62 | "EPS_DEFAULT": 1.0e-12,
63 | "WF_INTERPOLATION": "ps",
64 | "EXTRAPOLATION_ORDER": 3,
65 | },
66 | "MGRID": {
67 | "NGRIDS": 4,
68 | "CUTOFF": 280,
69 | "REL_CUTOFF": 30,
70 | },
71 | "XC": {
72 | "XC_FUNCTIONAL": {
73 | "_": "LDA",
74 | },
75 | },
76 | "POISSON": {
77 | "PERIODIC": "none",
78 | "PSOLVER": "MT",
79 | },
80 | "SCF": {"PRINT": {"RESTART": {"_": "ON"}}},
81 | },
82 | "SUBSYS": {
83 | "KIND": [
84 | {
85 | "_": "O",
86 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
87 | "POTENTIAL": "GTH-LDA-q6",
88 | },
89 | {
90 | "_": "H",
91 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
92 | "POTENTIAL": "GTH-LDA-q1",
93 | },
94 | ],
95 | },
96 | },
97 | }
98 | )
99 |
100 | # Construct process builder.
101 | builder = cp2k_code.get_builder()
102 |
103 | # Set up the first calculation.
104 | builder.structure = structure
105 | builder.parameters = params1
106 | builder.code = cp2k_code
107 | builder.file = {
108 | "basis": basis_file,
109 | "pseudo": pseudo_file,
110 | }
111 | builder.metadata.options.resources = {
112 | "num_machines": 1,
113 | "num_mpiprocs_per_machine": 1,
114 | }
115 | builder.metadata.options.max_wallclock_seconds = 1 * 2 * 60
116 |
117 | print("Submitted calculation 1.")
118 | calc1_outputs, calc1 = engine.run_get_node(builder)
119 |
120 | # Check walltime exceeded.
121 | if calc1.exit_status == 400:
122 | print("OK, walltime exceeded as expected.")
123 | else:
124 | print("FAIL, walltime wasn't exceeded as it should.")
125 | sys.exit(1)
126 |
127 | print(calc1_outputs)
128 | assert "output_structure" in calc1_outputs, "The output_structure is missing."
129 | print("OK, output_structure is present, even though the calculation has failed.")
130 |
131 | # Set up and start the second calculation.
132 |
133 | # Parameters.
134 | params2 = deepcopy(params1.get_dict())
135 | del params2["GLOBAL"]["WALLTIME"]
136 | del params2["MOTION"]["GEO_OPT"]["MAX_FORCE"]
137 | restart_wfn_fn = "./parent_calc/aiida-RESTART.wfn"
138 | params2["FORCE_EVAL"]["DFT"]["RESTART_FILE_NAME"] = restart_wfn_fn
139 | params2["FORCE_EVAL"]["DFT"]["SCF"]["SCF_GUESS"] = "RESTART"
140 | params2["EXT_RESTART"] = {"RESTART_FILE_NAME": "./parent_calc/aiida-1.restart"}
141 | params2 = orm.Dict(params2)
142 |
143 | # Structure.
144 | atoms2 = ase.io.read(os.path.join(thisdir, "..", "files", "h2o.xyz"))
145 | atoms2.positions *= 0.0 # place all atoms at origin -> nuclear fusion :-)
146 | structure2 = StructureData(ase=atoms2)
147 |
148 | # Update the process builder.
149 | builder.structure = structure2
150 | builder.parameters = params2
151 | builder.parent_calc_folder = calc1_outputs["remote_folder"]
152 |
153 | print("Submitted calculation 2.")
154 | calc2 = engine.run(builder)
155 |
156 | # Check energy.
157 | expected_energy = -17.1566455959
158 | if abs(calc2["output_parameters"]["energy"] - expected_energy) < 1e-10:
159 | print("OK, energy has the expected value.")
160 |
161 | # Ensure that this warning originates from overwritting coordinates.
162 | output = calc2["retrieved"].base.repository.get_object_content("aiida.out")
163 | assert re.search(
164 | "WARNING .* :: Overwriting coordinates", output
165 | ), "No warning about overwritting coordinates."
166 |
167 |
168 | @click.command("cli")
169 | @click.argument("codelabel")
170 | def cli(codelabel):
171 | """Click interface."""
172 | try:
173 | code = orm.load_code(codelabel)
174 | except common.NotExistent:
175 | print(f"The code '{codelabel}' does not exist.")
176 | sys.exit(1)
177 | example_restart(code)
178 |
179 |
180 | if __name__ == "__main__":
181 | cli()
182 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_sirius.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Run simple DFT with calculation with SIRIUS."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida import common, engine, orm, plugins
15 |
16 | StructureData = plugins.DataFactory("core.structure")
17 |
18 |
19 | def example_sirius(cp2k_code, setup_sssp_pseudos):
20 | """Run simple DFT calculation."""
21 |
22 | print("Testing CP2K SIRIUS ENERGY on Si (DFT)...")
23 |
24 | thisdir = os.path.dirname(os.path.realpath(__file__))
25 |
26 | # Structure.
27 | structure = StructureData(
28 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "si.xyz"))
29 | )
30 |
31 | # Parameters.
32 | parameters = orm.Dict(
33 | {
34 | "FORCE_EVAL": {
35 | "METHOD": "SIRIUS",
36 | "STRESS_TENSOR": "ANALYTICAL",
37 | "PRINT": {
38 | "FORCES": {"FILENAME": "requested-forces", "ADD_LAST": "SYMBOLIC"}
39 | },
40 | "PW_DFT": {
41 | "CONTROL": {"VERBOSITY": 2},
42 | "PARAMETERS": {
43 | "ELECTRONIC_STRUCTURE_METHOD": "pseudopotential",
44 | "USE_SYMMETRY": True,
45 | "GK_CUTOFF": 5,
46 | "PW_CUTOFF": 20,
47 | "ENERGY_TOL": 0.1,
48 | "DENSITY_TOL": 0.1,
49 | "NUM_DFT_ITER": 400,
50 | "SMEARING": "FERMI_DIRAC",
51 | "SMEARING_WIDTH": 0.00225,
52 | },
53 | "ITERATIVE_SOLVER": {
54 | "ENERGY_TOLERANCE": 0.001,
55 | "NUM_STEPS": 20,
56 | "SUBSPACE_SIZE": 4,
57 | "CONVERGE_BY_ENERGY": 1,
58 | },
59 | },
60 | "DFT": {
61 | "XC": {
62 | "XC_FUNCTIONAL": {
63 | "GGA_X_PBE": {"_": ""},
64 | "GGA_C_PBE": {"_": ""},
65 | }
66 | },
67 | "PRINT": {
68 | "MO": {
69 | "_": "OFF",
70 | "ADD_LAST": "SYMBOLIC",
71 | "EIGENVALUES": True,
72 | "OCCUPATION_NUMBERS": True,
73 | "NDIGITS": 12,
74 | "EACH": {"CELL_OPT": 0, "GEO_OPT": 0, "MD": 0, "QS_SCF": 0},
75 | },
76 | "MULLIKEN": {
77 | "_": "ON",
78 | "ADD_LAST": "SYMBOLIC",
79 | "EACH": {"CELL_OPT": 0, "GEO_OPT": 0, "MD": 0},
80 | },
81 | "LOWDIN": {"_": "OFF"},
82 | "HIRSHFELD": {"_": "OFF"},
83 | },
84 | },
85 | "SUBSYS": {
86 | "KIND": [
87 | {
88 | "_": "Si",
89 | "POTENTIAL": "UPF Si.json",
90 | },
91 | ],
92 | },
93 | },
94 | }
95 | )
96 |
97 | # Construct process builder.
98 | builder = cp2k_code.get_builder()
99 | builder.structure = structure
100 | builder.parameters = parameters
101 | builder.code = cp2k_code
102 | pseudo_family = orm.load_group("SSSP/1.3/PBE/efficiency")
103 | builder.pseudos_upf = pseudo_family.get_pseudos(structure=structure)
104 | builder.metadata.options.resources = {
105 | "num_machines": 1,
106 | "num_mpiprocs_per_machine": 1,
107 | }
108 | builder.metadata.options.max_wallclock_seconds = 1 * 3 * 60
109 |
110 | print("Submitted calculation...")
111 | engine.run(builder)
112 |
113 |
114 | @click.command("cli")
115 | @click.argument("codelabel")
116 | def cli(codelabel):
117 | """Click interface."""
118 | try:
119 | code = orm.load_code(codelabel)
120 | except common.NotExistent:
121 | print(f"The code '{codelabel}' does not exist.")
122 | sys.exit(1)
123 | example_sirius(code, setup_sssp_pseudos=None)
124 |
125 |
126 | if __name__ == "__main__":
127 | cli()
128 |
--------------------------------------------------------------------------------
/examples/single_calculations/example_structure_through_file.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Run simple DFT calculation"""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run
16 | from aiida.orm import Dict, SinglefileData, load_code
17 | from aiida.plugins import DataFactory
18 |
19 | StructureData = DataFactory("core.structure")
20 |
21 |
22 | def example_structure_through_file(cp2k_code):
23 | """Run simple DFT calculation"""
24 |
25 | print(
26 | "Testing CP2K ENERGY on H2O (DFT). Water molecule is provided through a file input..."
27 | )
28 |
29 | thisdir = os.path.dirname(os.path.realpath(__file__))
30 |
31 | # structure
32 | structure = StructureData(
33 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "h2o.xyz"))
34 | )
35 |
36 | # basis set
37 | basis_file = SinglefileData(
38 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
39 | )
40 |
41 | # pseudopotentials
42 | pseudo_file = SinglefileData(
43 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
44 | )
45 |
46 | # parameters
47 | parameters = Dict(
48 | {
49 | "FORCE_EVAL": {
50 | "METHOD": "Quickstep",
51 | "DFT": {
52 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
53 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
54 | "QS": {
55 | "EPS_DEFAULT": 1.0e-12,
56 | "WF_INTERPOLATION": "ps",
57 | "EXTRAPOLATION_ORDER": 3,
58 | },
59 | "MGRID": {
60 | "NGRIDS": 4,
61 | "CUTOFF": 280,
62 | "REL_CUTOFF": 30,
63 | },
64 | "XC": {
65 | "XC_FUNCTIONAL": {
66 | "_": "LDA",
67 | },
68 | },
69 | "POISSON": {
70 | "PERIODIC": "none",
71 | "PSOLVER": "MT",
72 | },
73 | },
74 | "SUBSYS": {
75 | "TOPOLOGY": {
76 | "COORD_FILE_NAME": "water.xyz",
77 | "COORD_FILE_FORMAT": "XYZ",
78 | },
79 | "CELL": {
80 | "ABC": "{:<15} {:<15} {:<15}".format(
81 | *[structure.cell[i][i] for i in range(3)]
82 | ),
83 | },
84 | "KIND": [
85 | {
86 | "_": "O",
87 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
88 | "POTENTIAL": "GTH-LDA-q6",
89 | },
90 | {
91 | "_": "H",
92 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
93 | "POTENTIAL": "GTH-LDA-q1",
94 | },
95 | ],
96 | },
97 | }
98 | }
99 | )
100 |
101 | # Construct process builder
102 | builder = cp2k_code.get_builder()
103 | builder.parameters = parameters
104 | builder.code = cp2k_code
105 | builder.file = {
106 | "basis": basis_file,
107 | "pseudo": pseudo_file,
108 | "water": structure,
109 | }
110 | builder.metadata.options.resources = {
111 | "num_machines": 1,
112 | "num_mpiprocs_per_machine": 1,
113 | }
114 | builder.metadata.options.max_wallclock_seconds = 1 * 3 * 60
115 |
116 | print("Submitted calculation...")
117 | run(builder)
118 |
119 |
120 | @click.command("cli")
121 | @click.argument("codelabel")
122 | def cli(codelabel):
123 | """Click interface"""
124 | try:
125 | code = load_code(codelabel)
126 | except NotExistent:
127 | print(f"The code '{codelabel}' does not exist.")
128 | sys.exit(1)
129 | example_structure_through_file(code)
130 |
131 |
132 | if __name__ == "__main__":
133 | cli()
134 |
--------------------------------------------------------------------------------
/examples/workchains/example_base_energy_restart.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """An example testing the restart calculation handler for ENERGY run in CP2K."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run_get_node
16 | from aiida.orm import Dict, SinglefileData, load_code
17 | from aiida.plugins import DataFactory, WorkflowFactory
18 |
19 | Cp2kBaseWorkChain = WorkflowFactory("cp2k.base")
20 | StructureData = DataFactory("core.structure")
21 |
22 |
23 | def example_base(cp2k_code):
24 | """Run simple DFT calculation through a workchain."""
25 |
26 | thisdir = os.path.dirname(os.path.realpath(__file__))
27 |
28 | print("Testing CP2K ENERGY on H2O (DFT) through a workchain...")
29 |
30 | # Basis set.
31 | basis_file = SinglefileData(
32 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
33 | )
34 |
35 | # Pseudopotentials.
36 | pseudo_file = SinglefileData(
37 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
38 | )
39 |
40 | # Structure.
41 | structure = StructureData(
42 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "h2o.xyz"))
43 | )
44 |
45 | # Parameters.
46 | parameters = Dict(
47 | {
48 | "GLOBAL": {
49 | "RUN_TYPE": "ENERGY",
50 | "WALLTIME": "00:00:30", # Not enough time to converge an SCF loop
51 | },
52 | "FORCE_EVAL": {
53 | "METHOD": "Quickstep",
54 | "DFT": {
55 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
56 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
57 | "QS": {
58 | "EPS_DEFAULT": 1.0e-16,
59 | "WF_INTERPOLATION": "ps",
60 | "EXTRAPOLATION_ORDER": 3,
61 | },
62 | "MGRID": {
63 | "NGRIDS": 4,
64 | "CUTOFF": 450,
65 | "REL_CUTOFF": 70,
66 | },
67 | "XC": {
68 | "XC_FUNCTIONAL": {
69 | "_": "LDA",
70 | },
71 | },
72 | "POISSON": {
73 | "PERIODIC": "none",
74 | "PSOLVER": "MT",
75 | },
76 | "SCF": {"PRINT": {"RESTART": {"_": "ON"}}},
77 | },
78 | "SUBSYS": {
79 | "KIND": [
80 | {
81 | "_": "O",
82 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
83 | "POTENTIAL": "GTH-LDA-q6",
84 | },
85 | {
86 | "_": "H",
87 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
88 | "POTENTIAL": "GTH-LDA-q1",
89 | },
90 | ],
91 | },
92 | },
93 | }
94 | )
95 |
96 | # Construct process builder.
97 | builder = Cp2kBaseWorkChain.get_builder()
98 |
99 | # Switch on resubmit_unconverged_geometry disabled by default.
100 | builder.handler_overrides = Dict(
101 | {"restart_incomplete_calculation": {"enabled": True}}
102 | )
103 |
104 | # Input structure.
105 | builder.cp2k.structure = structure
106 | builder.cp2k.parameters = parameters
107 | builder.cp2k.code = cp2k_code
108 | builder.cp2k.file = {
109 | "basis": basis_file,
110 | "pseudo": pseudo_file,
111 | }
112 | builder.cp2k.metadata.options = {
113 | "resources": {
114 | "num_machines": 1,
115 | "num_mpiprocs_per_machine": 1,
116 | },
117 | "max_wallclock_seconds": 1 * 1 * 60,
118 | }
119 |
120 | print("Submitted calculation...")
121 | _, process_node = run_get_node(builder)
122 |
123 | if process_node.exit_status == 0:
124 | print("Work chain is finished correctly.")
125 | else:
126 | print("ERROR! Work chain failed.")
127 | sys.exit(3)
128 |
129 |
130 | @click.command("cli")
131 | @click.argument("codelabel")
132 | def cli(codelabel):
133 | """Click interface."""
134 | try:
135 | code = load_code(codelabel)
136 | except NotExistent:
137 | print(f"The code '{codelabel}' does not exist")
138 | sys.exit(1)
139 | example_base(code)
140 |
141 |
142 | if __name__ == "__main__":
143 | cli()
144 |
--------------------------------------------------------------------------------
/examples/workchains/example_base_failed_restart.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """An example that fails due to lack of restart data."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run_get_node
16 | from aiida.orm import Dict, SinglefileData, load_code
17 | from aiida.plugins import DataFactory, WorkflowFactory
18 |
19 | Cp2kBaseWorkChain = WorkflowFactory("cp2k.base")
20 | StructureData = DataFactory("core.structure")
21 |
22 |
23 | def example_base(cp2k_code):
24 | """Run simple DFT calculation through a workchain."""
25 |
26 | thisdir = os.path.dirname(os.path.realpath(__file__))
27 |
28 | print("Testing CP2K ENERGY on H2O (DFT) through a workchain...")
29 |
30 | # Basis set.
31 | basis_file = SinglefileData(
32 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
33 | )
34 |
35 | # Pseudopotentials.
36 | pseudo_file = SinglefileData(
37 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
38 | )
39 |
40 | # Structure.
41 | structure = StructureData(
42 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "h2o.xyz"))
43 | )
44 |
45 | # Parameters.
46 | parameters = Dict(
47 | {
48 | "GLOBAL": {
49 | "RUN_TYPE": "ENERGY",
50 | },
51 | "FORCE_EVAL": {
52 | "METHOD": "Quickstep",
53 | "DFT": {
54 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
55 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
56 | "QS": {
57 | "EPS_DEFAULT": 1.0e-16,
58 | "WF_INTERPOLATION": "ps",
59 | "EXTRAPOLATION_ORDER": 3,
60 | },
61 | "MGRID": {
62 | "NGRIDS": 4,
63 | "CUTOFF": 450,
64 | "REL_CUTOFF": 70,
65 | },
66 | "XC": {
67 | "XC_FUNCTIONAL": {
68 | "_": "LDA",
69 | },
70 | },
71 | "POISSON": {
72 | "PERIODIC": "none",
73 | "PSOLVER": "MT",
74 | },
75 | "SCF": {"PRINT": {"RESTART": {"_": "ON"}}},
76 | },
77 | "SUBSYS": {
78 | "KIND": [
79 | {
80 | "_": "O",
81 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
82 | "POTENTIAL": "GTH-LDA-q6",
83 | },
84 | {
85 | "_": "H",
86 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
87 | "POTENTIAL": "GTH-LDA-q1",
88 | },
89 | ],
90 | },
91 | },
92 | }
93 | )
94 |
95 | # Construct process builder.
96 | builder = Cp2kBaseWorkChain.get_builder()
97 |
98 | # Switch on resubmit_unconverged_geometry disabled by default.
99 | builder.handler_overrides = Dict(
100 | {"restart_incomplete_calculation": {"enabled": True}}
101 | )
102 |
103 | # Input structure.
104 | builder.cp2k.structure = structure
105 | builder.cp2k.parameters = parameters
106 | builder.cp2k.code = cp2k_code
107 | builder.cp2k.file = {
108 | "basis": basis_file,
109 | "pseudo": pseudo_file,
110 | }
111 | builder.cp2k.metadata.options = {
112 | "resources": {
113 | "num_machines": 1,
114 | "num_mpiprocs_per_machine": 1,
115 | },
116 | "max_wallclock_seconds": 1 * 1 * 60, # 30 min
117 | "mpirun_extra_params": [
118 | "timeout",
119 | "1",
120 | ], # Kill the calculation after 1 second to test the restart failure.
121 | }
122 | print("Submitted calculation...")
123 | _, process_node = run_get_node(builder)
124 |
125 | if process_node.exit_status == 400:
126 | print("Work chain failure correctly recognized.")
127 | else:
128 | print("ERROR!")
129 | print("Work chain failure was not recognized.")
130 | sys.exit(3)
131 |
132 |
133 | @click.command("cli")
134 | @click.argument("codelabel")
135 | def cli(codelabel):
136 | """Click interface."""
137 | try:
138 | code = load_code(codelabel)
139 | except NotExistent:
140 | print(f"The code '{codelabel}' does not exist")
141 | sys.exit(1)
142 | example_base(code)
143 |
144 |
145 | if __name__ == "__main__":
146 | cli()
147 |
--------------------------------------------------------------------------------
/examples/workchains/example_base_geo_opt_ignore_converge_restart.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """An example testing the restart calculation handler for ENERGY run in CP2K."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run_get_node
16 | from aiida.orm import Dict, SinglefileData, load_code
17 | from aiida.plugins import DataFactory, WorkflowFactory
18 |
19 | Cp2kBaseWorkChain = WorkflowFactory("cp2k.base")
20 | StructureData = DataFactory("core.structure")
21 |
22 |
23 | def example_base(cp2k_code):
24 | """Run simple DFT calculation through a workchain."""
25 |
26 | thisdir = os.path.dirname(os.path.realpath(__file__))
27 |
28 | print("Testing CP2K ENERGY on H2O (DFT) through a workchain...")
29 |
30 | # Basis set.
31 | basis_file = SinglefileData(
32 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
33 | )
34 |
35 | # Pseudopotentials.
36 | pseudo_file = SinglefileData(
37 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
38 | )
39 |
40 | # Structure.
41 | structure = StructureData(
42 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "h2o.xyz"))
43 | )
44 |
45 | # Parameters.
46 | parameters = Dict(
47 | {
48 | "GLOBAL": {
49 | "RUN_TYPE": "GEO_OPT",
50 | },
51 | "FORCE_EVAL": {
52 | "METHOD": "Quickstep",
53 | "DFT": {
54 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
55 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
56 | "QS": {
57 | "EPS_DEFAULT": 1.0e-16,
58 | "WF_INTERPOLATION": "ps",
59 | "EXTRAPOLATION_ORDER": 3,
60 | },
61 | "MGRID": {
62 | "NGRIDS": 4,
63 | "CUTOFF": 450,
64 | "REL_CUTOFF": 70,
65 | },
66 | "XC": {
67 | "XC_FUNCTIONAL": {
68 | "_": "LDA",
69 | },
70 | },
71 | "POISSON": {
72 | "PERIODIC": "none",
73 | "PSOLVER": "MT",
74 | },
75 | "SCF": {
76 | "MAX_SCF": 10, # not enough to converge
77 | "EPS_SCF": "1.e-6",
78 | "PRINT": {"RESTART": {"_": "ON"}},
79 | },
80 | },
81 | "SUBSYS": {
82 | "KIND": [
83 | {
84 | "_": "O",
85 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
86 | "POTENTIAL": "GTH-LDA-q6",
87 | },
88 | {
89 | "_": "H",
90 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
91 | "POTENTIAL": "GTH-LDA-q1",
92 | },
93 | ],
94 | },
95 | },
96 | }
97 | )
98 |
99 | # Construct process builder.
100 | builder = Cp2kBaseWorkChain.get_builder()
101 |
102 | # Switch on resubmit_unconverged_geometry disabled by default.
103 | builder.handler_overrides = Dict(
104 | {"restart_incomplete_calculation": {"enabled": True}}
105 | )
106 |
107 | # Input structure.
108 | builder.cp2k.structure = structure
109 | builder.cp2k.parameters = parameters
110 | builder.cp2k.code = cp2k_code
111 | builder.cp2k.file = {
112 | "basis": basis_file,
113 | "pseudo": pseudo_file,
114 | }
115 | builder.cp2k.metadata.options = {
116 | "resources": {
117 | "num_machines": 1,
118 | "num_mpiprocs_per_machine": 1,
119 | },
120 | "max_wallclock_seconds": 1 * 10 * 60,
121 | }
122 |
123 | print("Submitted calculation...")
124 | _, process_node = run_get_node(builder)
125 |
126 | if process_node.exit_status == 0:
127 | print("Work chain is finished correctly.")
128 | else:
129 | print("ERROR! Work chain failed.")
130 | sys.exit(1)
131 |
132 |
133 | @click.command("cli")
134 | @click.argument("codelabel")
135 | def cli(codelabel):
136 | """Click interface."""
137 | try:
138 | code = load_code(codelabel)
139 | except NotExistent:
140 | print(f"The code '{codelabel}' does not exist")
141 | sys.exit(1)
142 | example_base(code)
143 |
144 |
145 | if __name__ == "__main__":
146 | cli()
147 |
--------------------------------------------------------------------------------
/examples/workchains/example_base_geoopt_restart.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """An example testing the restart calculation handler for geo_opt run in CP2K."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run
16 | from aiida.orm import Dict, SinglefileData, load_code
17 | from aiida.plugins import DataFactory, WorkflowFactory
18 |
19 | Cp2kBaseWorkChain = WorkflowFactory("cp2k.base")
20 | StructureData = DataFactory("core.structure")
21 |
22 |
23 | def example_base(cp2k_code):
24 | """Run simple DFT calculation through a workchain."""
25 |
26 | thisdir = os.path.dirname(os.path.realpath(__file__))
27 |
28 | print("Testing CP2K ENERGY on H2O (DFT) through a workchain...")
29 |
30 | # Basis set.
31 | basis_file = SinglefileData(
32 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
33 | )
34 |
35 | # Pseudopotentials.
36 | pseudo_file = SinglefileData(
37 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
38 | )
39 |
40 | # Structure.
41 | structure = StructureData(
42 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "h2o.xyz"))
43 | )
44 |
45 | # Parameters.
46 | parameters = Dict(
47 | {
48 | "GLOBAL": {
49 | "RUN_TYPE": "GEO_OPT",
50 | },
51 | "MOTION": {
52 | "GEO_OPT": {
53 | "MAX_ITER": 8,
54 | },
55 | },
56 | "FORCE_EVAL": {
57 | "METHOD": "Quickstep",
58 | "DFT": {
59 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
60 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
61 | "QS": {
62 | "EPS_DEFAULT": 1.0e-12,
63 | "WF_INTERPOLATION": "ps",
64 | "EXTRAPOLATION_ORDER": 3,
65 | },
66 | "MGRID": {
67 | "NGRIDS": 4,
68 | "CUTOFF": 280,
69 | "REL_CUTOFF": 30,
70 | },
71 | "XC": {
72 | "XC_FUNCTIONAL": {
73 | "_": "LDA",
74 | },
75 | },
76 | "POISSON": {
77 | "PERIODIC": "none",
78 | "PSOLVER": "MT",
79 | },
80 | "SCF": {"PRINT": {"RESTART": {"_": "ON"}}},
81 | },
82 | "SUBSYS": {
83 | "KIND": [
84 | {
85 | "_": "O",
86 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
87 | "POTENTIAL": "GTH-LDA-q6",
88 | },
89 | {
90 | "_": "H",
91 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
92 | "POTENTIAL": "GTH-LDA-q1",
93 | },
94 | ],
95 | },
96 | },
97 | }
98 | )
99 |
100 | # Construct process builder.
101 | builder = Cp2kBaseWorkChain.get_builder()
102 |
103 | # Switch on resubmit_unconverged_geometry disabled by default.
104 | builder.handler_overrides = Dict(
105 | {"restart_incomplete_calculation": {"enabled": True}}
106 | )
107 |
108 | # Input structure.
109 | builder.cp2k.structure = structure
110 | builder.cp2k.parameters = parameters
111 | builder.cp2k.code = cp2k_code
112 | builder.cp2k.file = {
113 | "basis": basis_file,
114 | "pseudo": pseudo_file,
115 | }
116 | builder.cp2k.metadata.options.resources = {
117 | "num_machines": 1,
118 | "num_mpiprocs_per_machine": 1,
119 | }
120 | builder.cp2k.metadata.options.max_wallclock_seconds = 1 * 3 * 60
121 |
122 | print("Submitted calculation...")
123 | calc = run(builder)
124 |
125 | if "EXT_RESTART" in calc["final_input_parameters"].dict:
126 | print("OK, EXT_RESTART section is present in the final_input_parameters.")
127 | else:
128 | print(
129 | "ERROR, EXT_RESTART section is NOT present in the final_input_parameters."
130 | )
131 | sys.exit(3)
132 |
133 |
134 | @click.command("cli")
135 | @click.argument("codelabel")
136 | def cli(codelabel):
137 | """Click interface."""
138 | try:
139 | code = load_code(codelabel)
140 | except NotExistent:
141 | print(f"The code '{codelabel}' does not exist")
142 | sys.exit(1)
143 | example_base(code)
144 |
145 |
146 | if __name__ == "__main__":
147 | cli()
148 |
--------------------------------------------------------------------------------
/examples/workchains/example_base_md_restart.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """An example testing the restart calculation handler for geo_opt run in CP2K."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | from aiida.common import NotExistent
15 | from aiida.engine import run
16 | from aiida.orm import Dict, SinglefileData, load_code
17 | from aiida.plugins import DataFactory, WorkflowFactory
18 |
19 | Cp2kBaseWorkChain = WorkflowFactory("cp2k.base")
20 | StructureData = DataFactory("core.structure")
21 |
22 |
23 | def example_base(cp2k_code):
24 | """Run simple DFT calculation through a workchain."""
25 |
26 | thisdir = os.path.dirname(os.path.realpath(__file__))
27 |
28 | print("Testing CP2K ENERGY on H2O (DFT) through a workchain...")
29 |
30 | # Basis set.
31 | basis_file = SinglefileData(
32 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
33 | )
34 |
35 | # Pseudopotentials.
36 | pseudo_file = SinglefileData(
37 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
38 | )
39 |
40 | # Structure.
41 | structure = StructureData(
42 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "h2o.xyz"))
43 | )
44 |
45 | # Parameters.
46 | parameters = Dict(
47 | {
48 | "GLOBAL": {
49 | "RUN_TYPE": "MD",
50 | "WALLTIME": "00:00:14", # too short
51 | },
52 | "FORCE_EVAL": {
53 | "METHOD": "Quickstep",
54 | "STRESS_TENSOR": "analytical",
55 | "DFT": {
56 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
57 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
58 | "QS": {
59 | "EPS_DEFAULT": 1.0e-12,
60 | "WF_INTERPOLATION": "ps",
61 | "EXTRAPOLATION_ORDER": 3,
62 | },
63 | "MGRID": {
64 | "NGRIDS": 4,
65 | "CUTOFF": 280,
66 | "REL_CUTOFF": 30,
67 | },
68 | "XC": {
69 | "XC_FUNCTIONAL": {
70 | "_": "LDA",
71 | },
72 | },
73 | "POISSON": {
74 | "PERIODIC": "none",
75 | "PSOLVER": "MT",
76 | },
77 | "SCF": {"PRINT": {"RESTART": {"_": "ON"}}},
78 | },
79 | "SUBSYS": {
80 | "KIND": [
81 | {
82 | "_": "O",
83 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
84 | "POTENTIAL": "GTH-LDA-q6",
85 | },
86 | {
87 | "_": "H",
88 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
89 | "POTENTIAL": "GTH-LDA-q1",
90 | },
91 | ],
92 | },
93 | },
94 | "MOTION": {
95 | "CONSTRAINT": {},
96 | "MD": {
97 | "THERMOSTAT": {"CSVR": {}, "TYPE": "csvr"},
98 | "BAROSTAT": {},
99 | "MAX_STEPS": 8,
100 | "STEPS": 10000,
101 | "ENSEMBLE": "npt_f",
102 | "TEMPERATURE": 300.0,
103 | },
104 | "PRINT": {
105 | "RESTART": {"EACH": {"MD": 1}},
106 | },
107 | },
108 | }
109 | )
110 |
111 | # Construct process builder.
112 | builder = Cp2kBaseWorkChain.get_builder()
113 |
114 | # Switch on resubmit_unconverged_geometry disabled by default.
115 | builder.handler_overrides = Dict(
116 | {"restart_incomplete_calculation": {"enabled": True}}
117 | )
118 |
119 | # Input structure.
120 | builder.cp2k.structure = structure
121 | builder.cp2k.parameters = parameters
122 | builder.cp2k.code = cp2k_code
123 | builder.cp2k.file = {
124 | "basis": basis_file,
125 | "pseudo": pseudo_file,
126 | }
127 | builder.cp2k.metadata.options.resources = {
128 | "num_machines": 1,
129 | "num_mpiprocs_per_machine": 1,
130 | }
131 | builder.cp2k.metadata.options.max_wallclock_seconds = 1 * 3 * 60
132 |
133 | print("Submitted calculation...")
134 | calc = run(builder)
135 |
136 | if "EXT_RESTART" in calc["final_input_parameters"].dict:
137 | print("OK, EXT_RESTART section is present in the final_input_parameters.")
138 | else:
139 | print(
140 | "ERROR, EXT_RESTART section is NOT present in the final_input_parameters."
141 | )
142 | sys.exit(3)
143 |
144 |
145 | @click.command("cli")
146 | @click.argument("codelabel")
147 | def cli(codelabel):
148 | """Click interface."""
149 | try:
150 | code = load_code(codelabel)
151 | except NotExistent:
152 | print(f"The code '{codelabel}' does not exist")
153 | sys.exit(1)
154 | example_base(code)
155 |
156 |
157 | if __name__ == "__main__":
158 | cli()
159 |
--------------------------------------------------------------------------------
/examples/workchains/fixme_example_base_md_reftraj_restart.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """An example testing the restart calculation handler for geo_opt run in CP2K."""
8 |
9 | import os
10 | import sys
11 |
12 | import ase.io
13 | import click
14 | import numpy as np
15 | from aiida import common, engine, orm, plugins
16 |
17 | Cp2kBaseWorkChain = plugins.WorkflowFactory("cp2k.base")
18 | StructureData = plugins.DataFactory("core.structure")
19 | TrajectoryData = plugins.DataFactory("core.array.trajectory")
20 |
21 |
22 | def example_base(cp2k_code):
23 | """Run simple DFT calculation through a workchain."""
24 |
25 | thisdir = os.path.dirname(os.path.realpath(__file__))
26 |
27 | print("Testing CP2K MD REFTRAJ on H2 (DFT) through a workchain...")
28 |
29 | # Basis set.
30 | basis_file = orm.SinglefileData(
31 | file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")
32 | )
33 |
34 | # Pseudopotentials.
35 | pseudo_file = orm.SinglefileData(
36 | file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")
37 | )
38 |
39 | # Structure.
40 | structure = StructureData(
41 | ase=ase.io.read(os.path.join(thisdir, "..", "files", "h2.xyz"))
42 | )
43 |
44 | # Trajectory.
45 | steps = 20
46 | positions = np.array([[[2, 2, 2.73 + 0.01 * i], [2, 2, 2]] for i in range(steps)])
47 | cells = np.array(
48 | [[[4, 0, 0], [0, 4, 0], [0, 0, 4.75 + 0.01 * i]] for i in range(steps)]
49 | )
50 | symbols = ["H", "H"]
51 | trajectory = TrajectoryData()
52 | trajectory.set_trajectory(symbols, positions, cells=cells)
53 |
54 | # Parameters.
55 | parameters = orm.Dict(
56 | {
57 | "GLOBAL": {
58 | "RUN_TYPE": "MD",
59 | "PRINT_LEVEL": "LOW",
60 | "WALLTIME": 2,
61 | "PROJECT": "aiida",
62 | },
63 | "MOTION": {
64 | "MD": {
65 | "ENSEMBLE": "REFTRAJ",
66 | "STEPS": steps,
67 | "REFTRAJ": {
68 | "FIRST_SNAPSHOT": 1,
69 | "LAST_SNAPSHOT": steps,
70 | "EVAL_FORCES": ".TRUE.",
71 | "TRAJ_FILE_NAME": "aiida-reftraj.xyz",
72 | "CELL_FILE_NAME": "aiida-reftraj.cell",
73 | "VARIABLE_VOLUME": ".TRUE.",
74 | },
75 | },
76 | "PRINT": {
77 | "RESTART": {
78 | "EACH": {
79 | "MD": 1,
80 | },
81 | },
82 | "FORCES": {
83 | "EACH": {
84 | "MD": 1,
85 | },
86 | },
87 | "CELL": {
88 | "EACH": {
89 | "MD": 1,
90 | },
91 | },
92 | },
93 | },
94 | "FORCE_EVAL": {
95 | "METHOD": "Quickstep",
96 | "DFT": {
97 | "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
98 | "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
99 | "QS": {
100 | "EPS_DEFAULT": 1.0e-12,
101 | "WF_INTERPOLATION": "ps",
102 | "EXTRAPOLATION_ORDER": 3,
103 | },
104 | "MGRID": {
105 | "NGRIDS": 4,
106 | "CUTOFF": 280,
107 | "REL_CUTOFF": 30,
108 | },
109 | "XC": {
110 | "XC_FUNCTIONAL": {
111 | "_": "LDA",
112 | },
113 | },
114 | "POISSON": {
115 | "PERIODIC": "none",
116 | "PSOLVER": "MT",
117 | },
118 | },
119 | "SUBSYS": {
120 | "KIND": [
121 | {
122 | "_": "O",
123 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
124 | "POTENTIAL": "GTH-LDA-q6",
125 | },
126 | {
127 | "_": "H",
128 | "BASIS_SET": "DZVP-MOLOPT-SR-GTH",
129 | "POTENTIAL": "GTH-LDA-q1",
130 | },
131 | ],
132 | },
133 | },
134 | }
135 | )
136 |
137 | # Construct process builder.
138 | builder = Cp2kBaseWorkChain.get_builder()
139 |
140 | # Switch on resubmit_unconverged_geometry disabled by default.
141 | builder.handler_overrides = orm.Dict(
142 | {"restart_incomplete_calculation": {"enabled": True}}
143 | )
144 |
145 | # Input structure.
146 | builder.cp2k.structure = structure
147 | builder.cp2k.trajectory = trajectory
148 | builder.cp2k.parameters = parameters
149 | builder.cp2k.code = cp2k_code
150 | builder.cp2k.file = {
151 | "basis": basis_file,
152 | "pseudo": pseudo_file,
153 | }
154 | builder.cp2k.metadata.options = {
155 | "max_wallclock_seconds": 100,
156 | "resources": {
157 | "num_machines": 1,
158 | "num_mpiprocs_per_machine": 1,
159 | },
160 | }
161 |
162 | print("Submitted calculation...")
163 | outputs, calc_node = engine.run_get_node(builder)
164 |
165 | if "EXT_RESTART" in outputs["final_input_parameters"].dict:
166 | print("OK, EXT_RESTART section is present in the final_input_parameters.")
167 | else:
168 | print(
169 | "ERROR, EXT_RESTART section is NOT present in the final_input_parameters."
170 | )
171 | sys.exit(1)
172 |
173 | # Check stepids extracted from each individual calculation.
174 | stepids = np.concatenate(
175 | [
176 | called.outputs.output_trajectory.get_stepids()
177 | for called in calc_node.called
178 | if isinstance(called, orm.CalcJobNode)
179 | ]
180 | )
181 |
182 | if np.all(stepids == np.arange(1, steps + 1)):
183 | print("OK, stepids are correct.")
184 | else:
185 | print(
186 | f"ERROR, stepids are NOT correct. Expected: {np.arange(1, steps + 1)} but got: {stepids}"
187 | )
188 | sys.exit(1)
189 |
190 | # Check the final trajectory.
191 | final_trajectory = outputs["output_trajectory"]
192 |
193 | if np.all(final_trajectory.get_stepids() == np.arange(1, steps + 1)):
194 | print("OK, final trajectory stepids are correct.")
195 | else:
196 | print(
197 | f"ERROR, final trajectory stepids are NOT correct. Expected: {np.arange(1, steps + 1)} but got: {final_trajectory.get_stepids()}"
198 | )
199 | sys.exit(1)
200 |
201 | if final_trajectory.get_positions().shape == (steps, len(structure.sites), 3):
202 | print("OK, the shape of the positions array is correct.")
203 | else:
204 | print(
205 | f"ERROR, the shape of the positions array is NOT correct. Expected: {(steps, len(structure.sites), 3)} but got: {final_trajectory.get_positions().shape}"
206 | )
207 | sys.exit(1)
208 |
209 | if final_trajectory.get_cells().shape == (steps, 3, 3):
210 | print("OK, the shape of the cells array is correct.")
211 | else:
212 | print(
213 | f"ERROR, the shape of the cells array is NOT correct. Expected: {(steps, 3, 3)} but got: {final_trajectory.get_cells().shape}"
214 | )
215 | sys.exit(1)
216 |
217 |
218 | @click.command("cli")
219 | @click.argument("codelabel")
220 | def cli(codelabel):
221 | """Click interface."""
222 | try:
223 | code = orm.load_code(codelabel)
224 | except common.NotExistent:
225 | print(f"The code '{codelabel}' does not exist")
226 | sys.exit(1)
227 | example_base(code)
228 |
229 |
230 | if __name__ == "__main__":
231 | cli()
232 |
--------------------------------------------------------------------------------
/miscellaneous/logos/MARVEL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiidateam/aiida-cp2k/c6b973e774c327066037544cff2e07f80a5fb4a4/miscellaneous/logos/MARVEL.png
--------------------------------------------------------------------------------
/miscellaneous/logos/MaX.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiidateam/aiida-cp2k/c6b973e774c327066037544cff2e07f80a5fb4a4/miscellaneous/logos/MaX.png
--------------------------------------------------------------------------------
/miscellaneous/logos/swissuniversities.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aiidateam/aiida-cp2k/c6b973e774c327066037544cff2e07f80a5fb4a4/miscellaneous/logos/swissuniversities.png
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["flit_core >=3.2,<4"]
3 | build-backend = "flit_core.buildapi"
4 |
5 | [tool.flit.module]
6 | name = "aiida_cp2k"
7 |
8 | [project]
9 | name = "aiida-cp2k"
10 | dynamic = ["version", "description"]
11 | readme = "README.md"
12 | license = {file = 'LICENSE.txt'}
13 | classifiers = [
14 | "Development Status :: 5 - Production/Stable",
15 | "Framework :: AiiDA",
16 | "License :: OSI Approved :: MIT License",
17 | "Operating System :: POSIX :: Linux",
18 | "Operating System :: MacOS :: MacOS X",
19 | "Programming Language :: Python :: 3",
20 | ]
21 | requires-python = ">=3.9"
22 | dependencies = [
23 | "aiida-core>=2.0.0,<3.0.0",
24 | "aiida-gaussian-datatypes",
25 | "ase",
26 | "ruamel.yaml>=0.16.5",
27 | "cp2k-output-tools",
28 | "aiida-pseudo~=1.2",
29 | "upf-to-json>=0.9",
30 | ]
31 |
32 | [[project.authors]]
33 | name = "The AiiDA team"
34 |
35 | [project.urls]
36 | Homepage = "https://github.com/aiidateam/aiida-cp2k"
37 |
38 | [project.optional-dependencies]
39 | dev = [
40 | "bumpver==2022.1119",
41 | "pgtest~=1.3",
42 | "pytest~=6.0",
43 | "pytest-cov~=2.11.1",
44 | "coverage",
45 | "pre-commit~=3.6",
46 | ]
47 | docs = [
48 | "sphinx",
49 | "sphinx-rtd-theme",
50 | "sphinxcontrib-contentui",
51 | "sphinxcontrib-details-directive",
52 | ]
53 |
54 | [project.entry-points."aiida.calculations"]
55 | cp2k = "aiida_cp2k.calculations:Cp2kCalculation"
56 |
57 | [project.entry-points."aiida.parsers"]
58 | cp2k_base_parser = "aiida_cp2k.parsers:Cp2kBaseParser"
59 | cp2k_advanced_parser = "aiida_cp2k.parsers:Cp2kAdvancedParser"
60 | cp2k_tools_parser = "aiida_cp2k.parsers:Cp2kToolsParser"
61 |
62 | [project.entry-points."aiida.workflows"]
63 | "cp2k.base" = "aiida_cp2k.workchains:Cp2kBaseWorkChain"
64 |
65 | [tool.pytest.ini_options]
66 | python_files = "test_*.py example_*.py"
67 | python_functions = "example_* test_*"
68 | filterwarnings = [
69 | "ignore::DeprecationWarning:aiida:",
70 | "ignore::DeprecationWarning:plumpy:",
71 | "ignore::DeprecationWarning:django:",
72 | "ignore::DeprecationWarning:frozendict:",
73 | "ignore::DeprecationWarning:sqlalchemy:",
74 | "ignore::DeprecationWarning:yaml:",
75 | "ignore::DeprecationWarning:pymatgen:",
76 | ]
77 |
78 | [tool.bumpver]
79 | current_version = "v2.1.1"
80 | version_pattern = "vMAJOR.MINOR.PATCH[PYTAGNUM]"
81 | commit_message = "Bump version {old_version} -> {new_version}."
82 | commit = true
83 | tag = true
84 | push = true
85 |
86 | [tool.bumpver.file_patterns]
87 | "aiida_cp2k/__init__.py" = [
88 | '__version__ = "{pep440_version}"',
89 | ]
90 |
--------------------------------------------------------------------------------
/test/outputs/PBC_output_none.restart:
--------------------------------------------------------------------------------
1 | &GLOBAL
2 | PROJECT_NAME aiida
3 | RUN_TYPE GEO_OPT
4 | &END GLOBAL
5 | &FORCE_EVAL
6 | METHOD QS
7 | &DFT
8 | BASIS_SET_FILE_NAME BASIS_MOLOPT
9 | POTENTIAL_FILE_NAME GTH_POTENTIALS
10 | &QS
11 | EPS_DEFAULT 9.9999999999999998E-13
12 | EXTRAPOLATION PS
13 | EXTRAPOLATION_ORDER 3
14 | &END QS
15 | &MGRID
16 | NGRIDS 4
17 | CUTOFF 2.8000000000000000E+02
18 | REL_CUTOFF 3.0000000000000000E+01
19 | &END MGRID
20 | &XC
21 | DENSITY_CUTOFF 1.0000000000000000E-10
22 | GRADIENT_CUTOFF 1.0000000000000000E-10
23 | TAU_CUTOFF 1.0000000000000000E-10
24 | &XC_FUNCTIONAL NO_SHORTCUT
25 | &PBE T
26 | &END PBE
27 | &END XC_FUNCTIONAL
28 | &END XC
29 | &POISSON
30 | POISSON_SOLVER MT
31 | PERIODIC NONE
32 | &END POISSON
33 | &END DFT
34 | &SUBSYS
35 | &CELL
36 | A 4.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00
37 | B 0.0000000000000000E+00 4.0000000000000000E+00 0.0000000000000000E+00
38 | C 0.0000000000000000E+00 0.0000000000000000E+00 4.7371660000000011E+00
39 | PERIODIC NONE
40 | MULTIPLE_UNIT_CELL 1 1 1
41 | &END CELL
42 | &COORD
43 | H1 2.0000000000000893E+00 1.9999999999999707E+00 2.7290247702949189E+00
44 | H1 2.0000000000000697E+00 2.0000000000001568E+00 2.0081412297053984E+00
45 | &END COORD
46 | &KIND O
47 | BASIS_SET DZVP-MOLOPT-SR-GTH
48 | POTENTIAL GTH-PBE-q6
49 | &END KIND
50 | &KIND H1
51 | ELEMENT H
52 | BASIS_SET DZVP-MOLOPT-SR-GTH
53 | POTENTIAL GTH-PBE-q1
54 | &POTENTIAL
55 | 1
56 | 0.2000000000000000E+00 2 -0.4178900440000000E+01 0.7244633100000000E+00
57 | 0
58 | # Potential name: GTH-PBE-Q1 for symbol: H
59 | # Potential read from the potential filename: GTH_POTENTIALS
60 | &END POTENTIAL
61 | &END KIND
62 | &TOPOLOGY
63 | COORD_FILE_NAME aiida.coords.xyz
64 | COORD_FILE_FORMAT XYZ
65 | NUMBER_OF_ATOMS 2
66 | MULTIPLE_UNIT_CELL 1 1 1
67 | &END TOPOLOGY
68 | &END SUBSYS
69 | &END FORCE_EVAL
70 |
--------------------------------------------------------------------------------
/test/outputs/PBC_output_xyz.restart:
--------------------------------------------------------------------------------
1 | &GLOBAL
2 | PROJECT_NAME aiida
3 | RUN_TYPE GEO_OPT
4 | &END GLOBAL
5 | &FORCE_EVAL
6 | METHOD QS
7 | &DFT
8 | BASIS_SET_FILE_NAME BASIS_MOLOPT
9 | POTENTIAL_FILE_NAME GTH_POTENTIALS
10 | &QS
11 | EPS_DEFAULT 9.9999999999999998E-13
12 | EXTRAPOLATION PS
13 | EXTRAPOLATION_ORDER 3
14 | &END QS
15 | &MGRID
16 | NGRIDS 4
17 | CUTOFF 2.8000000000000000E+02
18 | REL_CUTOFF 3.0000000000000000E+01
19 | &END MGRID
20 | &XC
21 | DENSITY_CUTOFF 1.0000000000000000E-10
22 | GRADIENT_CUTOFF 1.0000000000000000E-10
23 | TAU_CUTOFF 1.0000000000000000E-10
24 | &XC_FUNCTIONAL NO_SHORTCUT
25 | &PBE T
26 | &END PBE
27 | &END XC_FUNCTIONAL
28 | &END XC
29 | &POISSON
30 | POISSON_SOLVER MT
31 | PERIODIC NONE
32 | &END POISSON
33 | &END DFT
34 | &SUBSYS
35 | &CELL
36 | A 4.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00
37 | B 0.0000000000000000E+00 4.0000000000000000E+00 0.0000000000000000E+00
38 | C 0.0000000000000000E+00 0.0000000000000000E+00 4.7371660000000011E+00
39 | PERIODIC XYZ
40 | MULTIPLE_UNIT_CELL 1 1 1
41 | &END CELL
42 | &COORD
43 | H1 2.0000000000000893E+00 1.9999999999999707E+00 2.7290247702949189E+00
44 | H1 2.0000000000000697E+00 2.0000000000001568E+00 2.0081412297053984E+00
45 | &END COORD
46 | &KIND O
47 | BASIS_SET DZVP-MOLOPT-SR-GTH
48 | POTENTIAL GTH-PBE-q6
49 | &END KIND
50 | &KIND H1
51 | ELEMENT H
52 | BASIS_SET DZVP-MOLOPT-SR-GTH
53 | POTENTIAL GTH-PBE-q1
54 | &POTENTIAL
55 | 1
56 | 0.2000000000000000E+00 2 -0.4178900440000000E+01 0.7244633100000000E+00
57 | 0
58 | # Potential name: GTH-PBE-Q1 for symbol: H
59 | # Potential read from the potential filename: GTH_POTENTIALS
60 | &END POTENTIAL
61 | &END KIND
62 | &TOPOLOGY
63 | COORD_FILE_NAME aiida.coords.xyz
64 | COORD_FILE_FORMAT XYZ
65 | NUMBER_OF_ATOMS 2
66 | MULTIPLE_UNIT_CELL 1 1 1
67 | &END TOPOLOGY
68 | &END SUBSYS
69 | &END FORCE_EVAL
70 |
--------------------------------------------------------------------------------
/test/outputs/PBC_output_xz.restart:
--------------------------------------------------------------------------------
1 | &GLOBAL
2 | PROJECT_NAME aiida
3 | RUN_TYPE GEO_OPT
4 | &END GLOBAL
5 | &FORCE_EVAL
6 | METHOD QS
7 | &DFT
8 | BASIS_SET_FILE_NAME BASIS_MOLOPT
9 | POTENTIAL_FILE_NAME GTH_POTENTIALS
10 | &QS
11 | EPS_DEFAULT 9.9999999999999998E-13
12 | EXTRAPOLATION PS
13 | EXTRAPOLATION_ORDER 3
14 | &END QS
15 | &MGRID
16 | NGRIDS 4
17 | CUTOFF 2.8000000000000000E+02
18 | REL_CUTOFF 3.0000000000000000E+01
19 | &END MGRID
20 | &XC
21 | DENSITY_CUTOFF 1.0000000000000000E-10
22 | GRADIENT_CUTOFF 1.0000000000000000E-10
23 | TAU_CUTOFF 1.0000000000000000E-10
24 | &XC_FUNCTIONAL NO_SHORTCUT
25 | &PBE T
26 | &END PBE
27 | &END XC_FUNCTIONAL
28 | &END XC
29 | &POISSON
30 | POISSON_SOLVER MT
31 | PERIODIC NONE
32 | &END POISSON
33 | &END DFT
34 | &SUBSYS
35 | &CELL
36 | A 4.0000000000000000E+00 0.0000000000000000E+00 0.0000000000000000E+00
37 | B 0.0000000000000000E+00 4.0000000000000000E+00 0.0000000000000000E+00
38 | C 0.0000000000000000E+00 0.0000000000000000E+00 4.7371660000000011E+00
39 | PERIODIC XZ
40 | MULTIPLE_UNIT_CELL 1 1 1
41 | &END CELL
42 | &COORD
43 | H1 2.0000000000000893E+00 1.9999999999999707E+00 2.7290247702949189E+00
44 | H1 2.0000000000000697E+00 2.0000000000001568E+00 2.0081412297053984E+00
45 | &END COORD
46 | &KIND O
47 | BASIS_SET DZVP-MOLOPT-SR-GTH
48 | POTENTIAL GTH-PBE-q6
49 | &END KIND
50 | &KIND H1
51 | ELEMENT H
52 | BASIS_SET DZVP-MOLOPT-SR-GTH
53 | POTENTIAL GTH-PBE-q1
54 | &POTENTIAL
55 | 1
56 | 0.2000000000000000E+00 2 -0.4178900440000000E+01 0.7244633100000000E+00
57 | 0
58 | # Potential name: GTH-PBE-Q1 for symbol: H
59 | # Potential read from the potential filename: GTH_POTENTIALS
60 | &END POTENTIAL
61 | &END KIND
62 | &TOPOLOGY
63 | COORD_FILE_NAME aiida.coords.xyz
64 | COORD_FILE_FORMAT XYZ
65 | NUMBER_OF_ATOMS 2
66 | MULTIPLE_UNIT_CELL 1 1 1
67 | &END TOPOLOGY
68 | &END SUBSYS
69 | &END FORCE_EVAL
70 |
--------------------------------------------------------------------------------
/test/test_datatype_helpers.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pytest
3 | from aiida import orm
4 |
5 | from aiida_cp2k.utils import (
6 | merge_trajectory_data_non_unique,
7 | merge_trajectory_data_unique,
8 | )
9 |
10 |
11 | @pytest.mark.parametrize(
12 | "step_ranges",
13 | (
14 | [(1, 20), (21, 40)],
15 | [(1, 20), (15, 30)],
16 | [(1, 20), (21, 40), (41, 60)],
17 | [(1, 25), (21, 30), (31, 60), (45, 80)],
18 | ),
19 | )
20 | def test_merge_trajectory_data(step_ranges):
21 | def get_trajectory(step1=1, step2=20):
22 | nstes = step2 - step1 + 1
23 | positions = np.array(
24 | [
25 | [[2, 2, 2.73 + 0.05 * np.random.random()], [2, 2, 2]]
26 | for i in range(nstes)
27 | ]
28 | )
29 | cells = np.array(
30 | [
31 | [[4, 0, 0], [0, 4, 0], [0, 0, 4.75 + 0.05 * np.random.random()]]
32 | for i in range(nstes)
33 | ]
34 | )
35 | stepids = np.arange(step1, step2 + 1)
36 | symbols = ["H", "H"]
37 | trajectory = orm.TrajectoryData()
38 | trajectory.set_trajectory(symbols, positions, cells=cells, stepids=stepids)
39 | return trajectory
40 |
41 | trajectories = [get_trajectory(*step_range) for step_range in step_ranges]
42 |
43 | total_length = sum(
44 | [step_range[1] - step_range[0] + 1 for step_range in step_ranges]
45 | )
46 |
47 | unique_elements = []
48 | for step_range in step_ranges:
49 | unique_elements.extend(range(step_range[0], step_range[1] + 1))
50 | total_lenght_unique = len(set(unique_elements))
51 |
52 | merged_trajectory = merge_trajectory_data_non_unique(*trajectories)
53 | assert (
54 | len(merged_trajectory.get_stepids()) == total_length
55 | ), "The merged trajectory has the wrong length."
56 |
57 | merged_trajectory_unique = merge_trajectory_data_unique(*trajectories)
58 | assert (
59 | len(merged_trajectory_unique.get_stepids()) == total_lenght_unique
60 | ), "The merged trajectory with unique stepids has the wrong length."
61 |
--------------------------------------------------------------------------------
/test/test_input_generator.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/cp2k/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Test Cp2k input generator"""
8 |
9 | import pytest
10 |
11 | from aiida_cp2k.utils import Cp2kInput
12 |
13 |
14 | def test_render_empty():
15 | inp = Cp2kInput()
16 | assert inp.render() == inp.DISCLAIMER
17 |
18 |
19 | def test_render_str_val():
20 | inp = Cp2kInput({"FOO": "bar"})
21 | assert inp.render() == f"{inp.DISCLAIMER}\nFOO bar"
22 |
23 |
24 | def test_add_keyword():
25 | """Test add_keyword()"""
26 | inp = Cp2kInput({"FOO": "bar"})
27 | inp.add_keyword("BAR", "boo")
28 | assert inp.render() == f"{inp.DISCLAIMER}\nBAR boo\nFOO bar"
29 |
30 | inp.add_keyword("BOO/BAZ", "boo")
31 | assert (
32 | inp.render()
33 | == f"""{inp.DISCLAIMER}
34 | BAR boo
35 | &BOO
36 | BAZ boo
37 | &END BOO
38 | FOO bar"""
39 | )
40 |
41 | inp.add_keyword(["BOO", "BII"], "boo")
42 | assert (
43 | inp.render()
44 | == f"""{inp.DISCLAIMER}
45 | BAR boo
46 | &BOO
47 | BAZ boo
48 | BII boo
49 | &END BOO
50 | FOO bar"""
51 | )
52 |
53 | inp.add_keyword("BOO/BII", "bzzzzzz", override=False)
54 | assert (
55 | inp.render()
56 | == f"""{inp.DISCLAIMER}
57 | BAR boo
58 | &BOO
59 | BAZ boo
60 | BII boo
61 | &END BOO
62 | FOO bar"""
63 | )
64 |
65 | inp.add_keyword("BOO/BII/BCC", "bcr", override=False)
66 | assert (
67 | inp.render()
68 | == f"""{inp.DISCLAIMER}
69 | BAR boo
70 | &BOO
71 | BAZ boo
72 | BII boo
73 | &END BOO
74 | FOO bar"""
75 | )
76 |
77 | inp.add_keyword("BOO/BII/BCC", "bcr")
78 | assert (
79 | inp.render()
80 | == f"""{inp.DISCLAIMER}
81 | BAR boo
82 | &BOO
83 | BAZ boo
84 | &BII
85 | BCC bcr
86 | &END BII
87 | &END BOO
88 | FOO bar"""
89 | )
90 |
91 | inp.add_keyword("BOO/BII", "boo", override=False)
92 | assert (
93 | inp.render()
94 | == f"""{inp.DISCLAIMER}
95 | BAR boo
96 | &BOO
97 | BAZ boo
98 | &BII
99 | BCC bcr
100 | &END BII
101 | &END BOO
102 | FOO bar"""
103 | )
104 |
105 | inp.add_keyword("BOO/BII", "boo", override=True)
106 | assert (
107 | inp.render()
108 | == f"""{inp.DISCLAIMER}
109 | BAR boo
110 | &BOO
111 | BAZ boo
112 | BII boo
113 | &END BOO
114 | FOO bar"""
115 | )
116 |
117 | inp.add_keyword("BOO/BII", "boo", override=True)
118 | assert (
119 | inp.render()
120 | == f"""{inp.DISCLAIMER}
121 | BAR boo
122 | &BOO
123 | BAZ boo
124 | BII boo
125 | &END BOO
126 | FOO bar"""
127 | )
128 |
129 | inp.add_keyword("BOO/BIP", "bzz", override=False, conflicting_keys=["BII"])
130 | assert (
131 | inp.render()
132 | == f"""{inp.DISCLAIMER}
133 | BAR boo
134 | &BOO
135 | BAZ boo
136 | BII boo
137 | &END BOO
138 | FOO bar"""
139 | )
140 |
141 | inp.add_keyword("BOO/BIP", "bzz", override=False, conflicting_keys=[])
142 | assert (
143 | inp.render()
144 | == f"""{inp.DISCLAIMER}
145 | BAR boo
146 | &BOO
147 | BAZ boo
148 | BII boo
149 | BIP bzz
150 | &END BOO
151 | FOO bar"""
152 | )
153 |
154 | inp.add_keyword("BOO/BEE", "bee", override=True, conflicting_keys=["BAZ", "BII"])
155 | assert (
156 | inp.render()
157 | == f"""{inp.DISCLAIMER}
158 | BAR boo
159 | &BOO
160 | BEE bee
161 | BIP bzz
162 | &END BOO
163 | FOO bar"""
164 | )
165 |
166 |
167 | def test_add_keyword_invariant_inp():
168 | """Check that the input dictionary is not modified by add_keyword()"""
169 | param = {"FOO": "bar"}
170 | inp = Cp2kInput(param)
171 | inp.add_keyword("BAR", "boo")
172 | assert inp.render() == f"{inp.DISCLAIMER}\nBAR boo\nFOO bar"
173 | assert param == {"FOO": "bar"}
174 |
175 |
176 | def test_multiple_force_eval():
177 | inp = Cp2kInput({"FORCE_EVAL": [{"FOO": "bar"}, {"FOO": "bar"}, {"FOO": "bar"}]})
178 | assert (
179 | inp.render()
180 | == f"""{inp.DISCLAIMER}
181 | &FORCE_EVAL
182 | FOO bar
183 | &END FORCE_EVAL
184 | &FORCE_EVAL
185 | FOO bar
186 | &END FORCE_EVAL
187 | &FORCE_EVAL
188 | FOO bar
189 | &END FORCE_EVAL"""
190 | )
191 |
192 |
193 | def test_kinds():
194 | inp = Cp2kInput({"KIND": [{"_": "H"}, {"_": "O"}]})
195 | assert (
196 | inp.render()
197 | == f"""{inp.DISCLAIMER}
198 | &KIND H
199 | &END KIND
200 | &KIND O
201 | &END KIND"""
202 | )
203 |
204 |
205 | def test_invariant_under_render():
206 | """Check that the input dictionary is not modified by Cp2kInput.render()"""
207 | param = {"KIND": [{"_": "H"}, {"_": "O"}]}
208 | Cp2kInput(param).render()
209 | assert param == {"KIND": [{"_": "H"}, {"_": "O"}]}
210 |
211 | param = {"SEC": {"_": "H"}}
212 | Cp2kInput(param).render()
213 | assert param == {"SEC": {"_": "H"}}
214 |
215 |
216 | def test_invalid_lowercase_key():
217 | inp = Cp2kInput({"foo": "bar"})
218 | with pytest.raises(ValueError):
219 | inp.render()
220 |
221 |
222 | def test_invalid_preprocessor():
223 | inp = Cp2kInput({"@SET": "bar"})
224 | with pytest.raises(ValueError):
225 | inp.render()
226 |
--------------------------------------------------------------------------------
/test/test_xyz.py:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Copyright (c), The AiiDA-CP2K authors. #
3 | # SPDX-License-Identifier: MIT #
4 | # AiiDA-CP2K is hosted on GitHub at https://github.com/aiidateam/aiida-cp2k #
5 | # For further information on the license, see the LICENSE.txt file. #
6 | ###############################################################################
7 | """Test writing structures to xyz format"""
8 | from ase import Atoms
9 |
10 | from aiida_cp2k.calculations import _atoms_to_xyz
11 |
12 |
13 | def test_atoms_to_xyz():
14 | """Test that writing atoms to xyz format is handled correctly in the presence of tags"""
15 | h2o = Atoms("H2O")
16 | h2o[0].charge = -1
17 | h2o[0].tag = 1
18 | h2o[1].tag = 2
19 |
20 | xyz = _atoms_to_xyz(h2o)
21 |
22 | assert "H1" in xyz, xyz
23 | assert "H2" in xyz, xyz
24 |
--------------------------------------------------------------------------------