Skip to content

Commit

Permalink
Initial commit for automatic setup command
Browse files Browse the repository at this point in the history
  • Loading branch information
t-reents committed Jan 22, 2025
1 parent 172540b commit c9ec46b
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/aiida_quantumespresso/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,22 @@
from aiida.cmdline.params import options, types
import click

from .setup.setup_cmd import create_code


@click.group('aiida-quantumespresso', cls=VerdiCommandGroup, context_settings={'help_option_names': ['-h', '--help']})
@options.PROFILE(type=types.ProfileParamType(load_profile=True), expose_value=False)
def cmd_root():
"""CLI for the `aiida-quantumespresso` plugin."""


@cmd_root.group('setup')
def cmd_setup():
"""Commands to easily setup `code`s for Quantum ESPRESSO executables."""


cmd_setup.command('code')(create_code)

from .calculations import cmd_calculation
from .data import cmd_structure
from .workflows import cmd_workflow
2 changes: 2 additions & 0 deletions src/aiida_quantumespresso/cli/setup/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
"""Module with CLI commands to setup `code`s for Quantum ESPRESSO executables."""
127 changes: 127 additions & 0 deletions src/aiida_quantumespresso/cli/setup/setup_cmd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# -*- coding: utf-8 -*-
"""Command line interface commands for setting up `code`s for Quantum ESPRESSO executables."""
# -*- coding: utf-8 -*-
import pathlib

from aiida import orm
from aiida.cmdline.params import arguments
from aiida.cmdline.params.options.commands import code as options_code
from aiida.cmdline.utils import echo
from aiida.common.exceptions import NotExistent
import click


# add option to specify executables, otherwise try to set all that can be found in the directory
# documentation: this is equivalen to: list of executables e.g. pw.x dos. projwfc.x ...

# suffix: try to use curly brackets and f-strings {}_, show example in docstrings

# version in the name
# try to run verdi code test and parse version number
# --test option to run the test of code
# maybe, automatic test does only work if we don't submit
# just use transport to run code

@arguments.COMPUTER()
@click.argument('executables', nargs=-1, required=True)
@click.option('--directory', '-d', help='Absolute path to directory where the executbale(s) is (are) located.')
@click.option('--label_suffix', '-l', help='Suffix to append to the label of the code instance.', default='')
@options_code.PREPEND_TEXT()
@options_code.APPEND_TEXT()
def create_code(executables, computer, directory, label_suffix, **kwargs):
"""Create a `code` instance for a Quantum ESPRESSO executable."""
user = orm.User.collection.get_default()

try:
authinfo = computer.get_authinfo(user)
except NotExistent:
echo.echo_critical(f'Computer<{computer.label}> is not yet configured for user<{user.email}>')

if not authinfo.enabled:
echo.echo_warning(f'Computer<{computer.label}> is disabled for user<{user.email}>')
click.confirm('Do you really want to test it?', abort=True)

transport = authinfo.get_transport()

prepend_text = kwargs.pop('prepend_text', None)
executable_paths = []
with transport:
for executable in executables:
if not directory:
if prepend_text:
transport.exec_command_wait(prepend_text)

# Add prepend text to the command? Sometimes one might need to use modules before finding the executable
which_ret_val, exec_path, which_stderr = transport.exec_command_wait(f'which {executable}')

if which_ret_val != 0:
raise ValueError(
f'Failed to determine the path of the executable<{executable}> on '
f'computer<{computer.label}>: {which_stderr}'
)
else:
directory = pathlib.PurePosixPath(directory)
if not directory.is_absolute():
raise ValueError(f'Directory<{directory}> is not an absolute path.')
if not transport.path_exists(directory):
raise ValueError(f'Directory<{directory}> does not exist on computer<{computer.label}>')
exec_path = directory / executable
# also check that executable is executable and exists
executable_paths.append(str(exec_path))

for executable, exec_path in zip(executables, executable_paths):
label = f'{executable.replace(".x", "")}_{label_suffix}' if label_suffix else executable.replace(".x", "")
code = orm.InstalledCode(
label=label,
computer=computer,
filepath_executable=exec_path,
default_calc_job_plugin=f'quantumespresso.{executable.split(".")[0]}',
prepend_text=prepend_text
)
code.store()
echo.echo_success(f'Code<{code.label}> for {executable} created with pk<{code.pk}> on computer<{computer.label}>')

# add option --no-connect, makes -d mandatory
# In case you can not connect

# Run test, start code
# parse general information of the code e.g. simply run `pw.x` and append to extras
# extras can also be used to validate if things change

# aiida-quantumespresso code test
# run on login node
# --via-submit --> check report when it's done
# set extras on the code in the end

# set extras, option -- don't set extras
# md5 of the file
# version of the code
# compiled features? e.g. scalapack, hdf5, ...
# If md5 changes, fails --> optional force extras update
# Fails if others change as well

# test multiple codes
# use similar template from setup to run multiple codes that match the same pattern
# unless disabled, will also test code version and add it to the extras
# --provide-relabel-command/relabel-pattern=
# final report will show how to relabel codes based on the found information
# make it easily accessible to copy and paste

# relabel in interactive mode --relabel, -n option
# What to do if code with given label already exists?
# report existing codes and incrementing index, provide a command
# that could be run to add this

# check which spearator to use, dash might be confusing

# @cmd_setup.command('test')
# def test_code():
# """Test a `code` instance for a Quantum ESPRESSO executable."""
# from ase.build import bulk

# # Create a silicon crystal structure
# structure = bulk('Si')
# structure = orm.StructureData(ase=structure)

# # Create a Quantum ESPRESSO calculation
# calculation = orm.CalcJobNode()

0 comments on commit c9ec46b

Please sign in to comment.