Skip to content

Commit

Permalink
Docs: Add how-to guide for ph.x
Browse files Browse the repository at this point in the history
  • Loading branch information
sphuber committed Oct 26, 2022
1 parent 3f28fe3 commit 38f748a
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 7 deletions.
8 changes: 8 additions & 0 deletions .github/config/code-ph.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
label: ph
description: Quantum ESPRESSO ph.x
input_plugin: quantumespresso.ph
on_computer: true
computer: localhost
prepend_text: ' '
append_text: ' '
41 changes: 35 additions & 6 deletions .github/scripts/run_documentation_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,55 @@
import pathlib
import subprocess

from aiida.cmdline.utils.decorators import with_dbenv
import click

EXCLUDE_FILES = ('conf.py')
FILEPATH_DOCS = pathlib.Path(__file__).parent.parent.parent / 'docs' / 'source'

# Define the scripts that should be run and in which order
FILEPATH_SCRIPTS = (
FILEPATH_DOCS / 'tutorials' / 'include' / 'scripts' / 'run_pw_basic.py',
FILEPATH_DOCS / 'tutorials' / 'include' / 'scripts' / 'run_ph_basic.py',
)


def get_pw_calculation_pk():
"""Return the pk of the first ``PwCalculation`` that is found."""
from aiida.orm import CalcJobNode, QueryBuilder
return QueryBuilder().append(
CalcJobNode, filters={
'process_type': 'aiida.calculations:quantumespresso.pw'
}, project='id'
).first(flat=True)


@with_dbenv()
def main():
"""Run scripts from the documentation to verify they run without exceptions."""
filepath_docs = pathlib.Path(__file__).parent.parent.parent / 'docs' / 'source'
filepath_scripts = filepath_docs.glob('**/*.py')

for filepath in filter(lambda p: str(p.relative_to(filepath_docs)) not in EXCLUDE_FILES, filepath_scripts):
click.echo(f'Running: {filepath.relative_to(filepath_docs)} ...', nl=False)
# Mapping of placeholder strings in the scripts that should be replaced with the return value of the callable
placeholder_replacement = {
'IDENTIFIER_PW_CALCULATION': get_pw_calculation_pk,
}

for filepath in FILEPATH_SCRIPTS:

filepath_content = filepath.read_text()

for key, function in placeholder_replacement.items():
if key in filepath_content:
filepath_content.replace(key, str(function()))

filepath.write_text(filepath_content)

click.echo(f'Running: {filepath.relative_to(FILEPATH_DOCS)} ...', nl=False)
try:
stdout = subprocess.check_output(['verdi', 'run', str(filepath)])
except subprocess.CalledProcessError:
click.secho('[ERROR]', fg='red', bold=True)
click.echo(stdout)
else:
click.secho('[OK]', fg='green', bold=True)
click.echo(stdout)


if __name__ == '__main__':
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ jobs:
- name: Setup `pw.x`
run: verdi code setup -n --config .github/config/code-pw.yaml --remote-abs-path $(which pw.x)

- name: Setup `ph.x`
run: verdi code setup -n --config .github/config/code-ph.yaml --remote-abs-path $(which ph.x)

- name: Setup SSSP
run: aiida-pseudo install sssp

Expand Down
69 changes: 68 additions & 1 deletion docs/source/howto/calculations/ph.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,71 @@
``ph.x``
--------

*To be added.*
The ``ph.x`` code of Quantum ESPRESSO is used to compute phonons using density-functional perturbation theory.

================== ===============================================================================
Plugin class :class:`~aiida_quantumespresso.calculations.ph.PhCalculation`
Plugin entry point ``quantumespresso.ph``
================== ===============================================================================


How to launch a ``ph.x`` calculation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. note::

In order to run a ``ph.x`` calculation, you first need to have completed a ``pw.x`` calculation.
See the :ref:`tutorial <tutorials:pw-through-api>` or :ref:`how-to guide <howto:calculations:pw>` for more information.

Once you have successfully run a ``PwCalculation`` you can run a ``ph.x`` calculation through the ``PhCalculation`` plugin as follows:

.. literalinclude:: ../../tutorials/include/scripts/run_ph_basic.py
:language: python

Note that you will have to replace ``IDENTIFIER_PW_CALCULATION`` with the identifier (pk or UUID) of the completed ``PwCalculation``.


How to define input file parameters
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The ``ph.x`` code supports many parameters that can be defined through the input file, as shown on the `official documentation <https://www.quantum-espresso.org/Doc/INPUT_PH.html>`_.
Parameters that are part of the ``INPUTPH`` card should be specified through the ``parameters`` input of the ``PwCalculation`` plugin.
The parameters are specified using a Python dictionary, for example:

.. code-block:: python
parameters = {
'INPUTPH': {
'tr2_ph' : 1.0e-8,
'epsil' : True,
'ldisp' : True,
}
}
The parameters dictionary should be wrapped in a :class:`~aiida.orm.nodes.data.dict.Dict` node and assigned to the ``parameters`` input of the process builder:

.. code-block:: python
from aiida.orm import Dict, load_code
builder = load_code('ph').get_builder()
parameters = {
...
}
builder.parameters = Dict(parameters)
The q-points of the input file are specified with a ``KpointsData`` node through the ``qpoints`` input of the ``PhCalculation`` plugin.

.. warning::

There are a number of input parameters that *cannot* be set, as they will be automatically set by the plugin based on other inputs, such as the ``structure``.
These include:

* ``INPUTPH.outdir``
* ``INPUTPH.verbosity``
* ``INPUTPH.prefix``
* ``INPUTPH.fildyn``
* ``INPUTPH.ldisp``
* ``INPUTPH.nq1``
* ``INPUTPH.nq2``
* ``INPUTPH.nq3``
* ``INPUTPH.qplot``
33 changes: 33 additions & 0 deletions docs/source/tutorials/include/scripts/run_ph_basic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env runaiida
# -*- coding: utf-8 -*-
from aiida.engine import run
from aiida.orm import Dict, KpointsData, StructureData, load_code, load_group

# Load the code configured for ``ph.x``. Make sure to replace this string
# with the label of a ``Code`` that you configured in your profile.
code = load_code('ph@localhost')
builder = code.get_builder()

# Replace ``IDENTIFIER_PW_CALCULATION`` with the pk of the completed ``PwCalculation``
builder.parent_folder = load_code(IDENTIFIER_PW_CALCULATION).outputs.remote_folder
builder.parameters = Dict({'INPUTPH': {}})

# Generate a 1x1x1 q-point mesh
qpoints = KpointsData()
qpoints.set_kpoints_mesh([1, 1, 1])
builder.qpoints = qpoints

# Run the calculation on 1 CPU and kill it if it runs longer than 1800 seconds.
# Set ``withmpi`` to ``False`` if ``ph.x`` was compiled without MPI support.
builder.metadata.options = {
'resources': {
'num_machines': 1,
},
'max_wallclock_seconds': 1800,
'withmpi': False,
}

results, node = run.get_node(builder)
print(f'Calculation: {node.process_class}<{node.pk}> {node.process_state.value} [{node.exit_status}]')
print(f'Results: {results}')
assert node.is_finished_ok, f'{node} failed: [{node.exit_status}] {node.exit_message}'

0 comments on commit 38f748a

Please sign in to comment.