Skip to content

Commit

Permalink
Merge branch 'main' into pre-commit-ci-update-config
Browse files Browse the repository at this point in the history
  • Loading branch information
yakutovicha committed Mar 18, 2024
2 parents 882789a + a2a6d97 commit febe7b6
Show file tree
Hide file tree
Showing 26 changed files with 1,041 additions and 133 deletions.
1 change: 0 additions & 1 deletion .docker/cp2k-code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ label: cp2k
computer: localhost
description:
default_calc_job_plugin: cp2k
on_computer: True
filepath_executable: /usr/bin/cp2k
append_text:
prepend_text:
2 changes: 1 addition & 1 deletion .docker/opt/add-codes.sh → .docker/init/add-codes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ set -x
export SHELL=/bin/bash

# Install cp2k code.
verdi code show cp2k@localhost || verdi code create core.code.installed --config /opt/aiida-cp2k/.docker/cp2k-code.yml --non-interactive
verdi code show cp2k@localhost || verdi code create core.code.installed --config /home/aiida/aiida-cp2k/.docker/cp2k-code.yml --non-interactive
7 changes: 0 additions & 7 deletions .docker/my_init.d/add-codes.sh

This file was deleted.

8 changes: 0 additions & 8 deletions .docker/my_init.d/add-pgsql-bin-to-path.sh

This file was deleted.

Empty file.
1 change: 1 addition & 0 deletions .docker/s6-rc.d/cp2k-code-setup/timeout-up
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0
1 change: 1 addition & 0 deletions .docker/s6-rc.d/cp2k-code-setup/type
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
oneshot
7 changes: 7 additions & 0 deletions .docker/s6-rc.d/cp2k-code-setup/up
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/command/execlineb -S0

with-contenv

foreground { s6-echo "Setting up CP2K code" }

/etc/init/add-codes.sh
Empty file added .docker/user/cp2k-code-setup
Empty file.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ jobs:
- name: Create container from aiida_cp2k_test image and test the plugin inside
run: |
export DOCKERID=`docker run -d aiida_cp2k_test`
docker exec --tty $DOCKERID wait-for-services
sleep 5
docker logs $DOCKERID
docker exec --tty --user aiida $DOCKERID /bin/bash -l -c 'cd /opt/aiida-cp2k/ && py.test --cov aiida_cp2k --cov-append .'
docker exec --tty --user aiida $DOCKERID /bin/bash -l -c 'cd /home/aiida/aiida-cp2k/ && py.test --cov aiida_cp2k --cov-append .'
docs:
Expand Down
16 changes: 8 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
# For further information on the license, see the LICENSE.txt file. #
###############################################################################

FROM aiidateam/aiida-core:2.1.2

FROM aiidateam/aiida-core-with-services:2.5.0

# To prevent the container to exit prematurely.
ENV KILL_ALL_RPOCESSES_TIMEOUT=50

WORKDIR /opt/

USER root
# Install statically linked CP2K which is a considerably newer release than Debian builtin.
# The statically linked CP2K is a non-MPI binary, but we're running all tests with 1 MPI proc.
RUN set -ex ; \
Expand All @@ -21,16 +22,15 @@ RUN set -ex ; \
echo "1e6fccf901873ebe9c827f45fb29331f599772f6e6281e988d8956c7a3aa143c /usr/bin/cp2k" | sha256sum -c ; \
chmod +x /usr/bin/cp2k

USER aiida
# Install aiida-cp2k plugin.
COPY . aiida-cp2k
COPY --chown="${SYSTEM_UID}:${SYSTEM_GID}" . /home/aiida/aiida-cp2k
RUN pip install ./aiida-cp2k[dev,docs]

# Install coverals.
RUN pip install coveralls

# Install the cp2k code.
COPY .docker/opt/add-codes.sh /opt/
COPY .docker/my_init.d/add-codes.sh /etc/my_init.d/50_add-codes.sh

# Add PGSQL bin folder to PATH.
COPY .docker/my_init.d/add-pgsql-bin-to-path.sh /etc/my_init.d/50_add-pgsql-bin-to-path.sh
COPY .docker/init/add-codes.sh /etc/init/
COPY .docker/s6-rc.d/cp2k-code-setup /etc/s6-overlay/s6-rc.d/cp2k-code-setup
COPY .docker/user/cp2k-code-setup /etc/s6-overlay/s6-rc.d/user/contents.d/cp2k-code-setup
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pip install -e . # Also installs aiida, if missing (but not postgres/rabbitmq).

## For maintainers

### Release

To create a new release, clone the repository, install development dependencies with `pip install '.[dev]'`, and then execute `bumpver update --major/--minor/--patch`.
This will:

Expand All @@ -43,6 +45,33 @@ Additional notes:
- The release tag (e.g. a/b/rc) is determined from the last release.
Use the `--tag` option to override the release tag.

### Testing

To run the tests, you need to have Docker installed in your system.
Once this is done, you can build the Docker image with the following command:

```bash
docker build -t aiida_cp2k_test .
```
Then, you can launch the container:

```bash
DOKERID=`docker run -d aiida_cp2k_test`
```
This will remeber the container ID in the variable `DOKERID`.
You can then run the tests with the following command:

```bash
docker exec --tty --user aiida $DOCKERID /bin/bash -l -c 'cd /home/aiida/aiida-cp2k/ && pytest'
```

To enter the container for manual testing do:

```bash
docker exec -it --user aiida $DOCKERID bash
```


## License

MIT
Expand Down
2 changes: 1 addition & 1 deletion aiida_cp2k/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
###############################################################################
"""The official AiiDA plugin for CP2K."""

__version__ = "2.0.0"
__version__ = "2.1.0b1"

# EOF
95 changes: 92 additions & 3 deletions aiida_cp2k/calculations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from operator import add

import numpy as np
from aiida.common import CalcInfo, CodeInfo, InputValidationError
from aiida.engine import CalcJob
from aiida.orm import Dict, RemoteData, SinglefileData
Expand All @@ -25,6 +26,7 @@

BandsData = DataFactory("core.array.bands")
StructureData = DataFactory("core.structure")
TrajectoryData = DataFactory("core.array.trajectory")
KpointsData = DataFactory("core.array.kpoints")


Expand All @@ -40,8 +42,13 @@ class Cp2kCalculation(CalcJob):
_DEFAULT_PROJECT_NAME = "aiida"
_DEFAULT_RESTART_FILE_NAME = _DEFAULT_PROJECT_NAME + "-1.restart"
_DEFAULT_TRAJECT_FILE_NAME = _DEFAULT_PROJECT_NAME + "-pos-1.dcd"
_DEFAULT_TRAJECT_XYZ_FILE_NAME = _DEFAULT_PROJECT_NAME + "-pos-1.xyz"
_DEFAULT_TRAJECT_FORCES_FILE_NAME = _DEFAULT_PROJECT_NAME + "-frc-1.xyz"
_DEFAULT_TRAJECT_CELL_FILE_NAME = _DEFAULT_PROJECT_NAME + "-1.cell"
_DEFAULT_PARENT_CALC_FLDR_NAME = "parent_calc/"
_DEFAULT_COORDS_FILE_NAME = "aiida.coords.xyz"
_DEFAULT_COORDS_FILE_NAME = _DEFAULT_PROJECT_NAME + ".coords.xyz"
_DEFAULT_INPUT_TRAJECT_XYZ_FILE_NAME = _DEFAULT_PROJECT_NAME + "-reftraj.xyz"
_DEFAULT_INPUT_CELL_FILE_NAME = _DEFAULT_PROJECT_NAME + "-reftraj.cell"
_DEFAULT_PARSER = "cp2k_base_parser"

@classmethod
Expand All @@ -56,6 +63,12 @@ def define(cls, spec):
required=False,
help="The main input structure.",
)
spec.input(
"trajectory",
valid_type=TrajectoryData,
required=False,
help="Input trajectory for a REFTRAJ simulation.",
)
spec.input(
"settings",
valid_type=Dict,
Expand Down Expand Up @@ -162,6 +175,24 @@ def define(cls, spec):
"ERROR_STRUCTURE_PARSE",
message="The output structure could not be parsed.",
)
spec.exit_code(
321,
"ERROR_COORDINATES_TRAJECTORY_READ",
message="The coordinates trajectory file could not be read.",
)

spec.exit_code(
323,
"ERROR_FORCES_TRAJECTORY_READ",
message="The forces trajectory file could not be read.",
)

spec.exit_code(
325,
"ERROR_CELLS_TRAJECTORY_READ",
message="The cells trajectory file could not be read.",
)

spec.exit_code(
350,
"ERROR_UNEXPECTED_PARSER_EXCEPTION",
Expand Down Expand Up @@ -198,6 +229,12 @@ def define(cls, spec):
required=False,
help="The relaxed output structure.",
)
spec.output(
"output_trajectory",
valid_type=TrajectoryData,
required=False,
help="The output trajectory.",
)
spec.output(
"output_bands",
valid_type=BandsData,
Expand Down Expand Up @@ -249,6 +286,15 @@ def prepare_for_submission(self, folder):
conflicting_keys=["COORDINATE"],
)

# Create input trajectory files
if "trajectory" in self.inputs:
self._write_trajectories(
self.inputs.trajectory,
folder,
self._DEFAULT_INPUT_TRAJECT_XYZ_FILE_NAME,
self._DEFAULT_INPUT_CELL_FILE_NAME,
)

if "basissets" in self.inputs:
validate_basissets(
inp,
Expand Down Expand Up @@ -329,6 +375,9 @@ def prepare_for_submission(self, folder):
self._DEFAULT_OUTPUT_FILE,
self._DEFAULT_RESTART_FILE_NAME,
self._DEFAULT_TRAJECT_FILE_NAME,
self._DEFAULT_TRAJECT_XYZ_FILE_NAME,
self._DEFAULT_TRAJECT_FORCES_FILE_NAME,
self._DEFAULT_TRAJECT_CELL_FILE_NAME,
]
calcinfo.retrieve_list += settings.pop("additional_retrieve_list", [])

Expand Down Expand Up @@ -364,6 +413,19 @@ def _write_structure(structure, folder, name):
with open(folder.get_abs_path(name), mode="w", encoding="utf-8") as fobj:
fobj.write(xyz)

@staticmethod
def _write_trajectories(trajectory, folder, name_pos, name_cell):
"""Function that writes a structure and takes care of element tags."""

(xyz, cell) = _trajectory_to_xyz_and_cell(trajectory)
with open(folder.get_abs_path(name_pos), mode="w", encoding="utf-8") as fobj:
fobj.write(xyz)
if cell is not None:
with open(
folder.get_abs_path(name_cell), mode="w", encoding="utf-8"
) as fobj:
fobj.write(cell)


def kind_names(atoms):
"""Get atom kind names from ASE atoms based on tags.
Expand All @@ -378,7 +440,7 @@ def kind_names(atoms):
return list(map(add, atoms.get_chemical_symbols(), elem_tags))


def _atoms_to_xyz(atoms):
def _atoms_to_xyz(atoms, infoline="No info"):
"""Converts ASE atoms to string, taking care of element tags.
:param atoms: ASE Atoms instance
Expand All @@ -388,6 +450,33 @@ def _atoms_to_xyz(atoms):
elem_coords = [
f"{p[0]:25.16f} {p[1]:25.16f} {p[2]:25.16f}" for p in atoms.get_positions()
]
xyz = f"{len(elem_coords)}\n\n"
xyz = f"{len(elem_coords)}\n"
xyz += f"{infoline}\n"
xyz += "\n".join(map(add, elem_symbols, elem_coords))
return xyz


def _trajectory_to_xyz_and_cell(trajectory):
"""Converts postions and cell from a TrajectoryData to string, taking care of element tags from ASE atoms.
:param atoms: ASE Atoms instance
:param trajectory: TrajectoryData instance
:returns: positions str (in xyz format) and cell str
"""
cell = None
xyz = ""
stepids = trajectory.get_stepids()
for i, step in enumerate(stepids):
xyz += _atoms_to_xyz(
trajectory.get_step_structure(i).get_ase(),
infoline=f"i = {step+1} , time = {(step+1)*0.5}", # reftraj trajectories cannot start from STEP 0
)
xyz += "\n"
if "cells" in trajectory.get_arraynames():
cell = "# Step Time [fs] Ax [Angstrom] Ay [Angstrom] Az [Angstrom] Bx [Angstrom] By [Angstrom] Bz [Angstrom] Cx [Angstrom] Cy [Angstrom] Cz [Angstrom] Volume [Angstrom^3]\n"
cell_vecs = [
f"{stepid+1} {(stepid+1)*0.5:6.3f} {cellvec[0][0]:25.16f} {cellvec[0][1]:25.16f} {cellvec[0][2]:25.16f} {cellvec[1][0]:25.16f} {cellvec[1][1]:25.16f} {cellvec[1][2]:25.16f} {cellvec[2][0]:25.16f} {cellvec[2][1]:25.16f} {cellvec[2][2]:25.16f} {np.dot(cellvec[0],np.cross(cellvec[1],cellvec[2]))}"
for (stepid, cellvec) in zip(stepids, trajectory.get_array("cells"))
]
cell += "\n".join(cell_vecs)
return xyz, cell
Loading

0 comments on commit febe7b6

Please sign in to comment.