diff --git a/Dockerfile b/Dockerfile index 3f6b55c0..4235aec0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,30 +7,31 @@ FROM aiidateam/aiida-docker-stack -# Install cp2k -RUN apt-get update && apt-get install -y --no-install-recommends \ - cp2k - -# Set HOME variable: +# Set HOME and PATH variables: ENV HOME="/home/aiida" +ENV PATH="${HOME}/.local/bin:${PATH}" + +# Install cp2k +RUN apt-get update && apt-get install -y --no-install-recommends cp2k -# Install aiida-cp2k +# Copy local aiida-cp2k folder and change permissions COPY . ${HOME}/code/aiida-cp2k RUN chown -R aiida:aiida ${HOME}/code -# Install AiiDA +# Now do everything as the aiida user USER aiida -ENV PATH="${HOME}/.local/bin:${PATH}" -# Install aiida-cp2k plugin and coveralls +# Set the plugin folder as the workdir WORKDIR ${HOME}/code/aiida-cp2k + +# Install aiida-cp2k plugin and coveralls RUN pip install --user .[pre-commit,test] RUN pip install --user coveralls # Populate reentry cache for aiida user https://pypi.python.org/pypi/reentry/ RUN reentry scan -# Install the cp2k code +# Install the CP2K code to AiiDA COPY .docker/opt/add-codes.sh /opt/ COPY .docker/my_init.d/add-codes.sh /etc/my_init.d/40_add-codes.sh diff --git a/aiida_cp2k/fixers/geometry_optimization.py b/aiida_cp2k/fixers/geometry_optimization.py index 0a41c6ce..8a62a5e6 100644 --- a/aiida_cp2k/fixers/geometry_optimization.py +++ b/aiida_cp2k/fixers/geometry_optimization.py @@ -7,7 +7,7 @@ @calcfunction -def add_restart_section(input_dict): +def add_restart_sections(input_dict): """Add restart section to the input dictionary.""" params = input_dict.get_dict() restart_wfn_dict = { @@ -27,23 +27,50 @@ def add_restart_section(input_dict): def resubmit_unconverged_geometry(workchain, calc): """Resubmit a calculation it is not converged, but can be recovered.""" + content_string = calc.outputs.retrieved.get_object_content(calc.get_attribute('output_filename')) time_not_exceeded = "PROGRAM ENDED AT" time_exceeded = "exceeded requested execution time" one_step_done = "Max. gradient =" + workchain.ctx.inputs.parent_calc_folder = calc.outputs.remote_folder + params = workchain.ctx.inputs.parameters + # If the problem is recoverable then do restart if (time_not_exceeded not in content_string or time_exceeded in content_string) and one_step_done in content_string: - workchain.ctx.inputs.parameters = add_restart_section(workchain.ctx.inputs.parameters) - workchain.ctx.inputs.parent_calc_folder = calc.outputs.remote_folder - workchain.report("Could fix the problem") + try: + # Firts check if all the restart keys are present in the input dictionary + wf_rest_fname_pointer = params['FORCE_EVAL']['DFT']['RESTART_FILE_NAME'] + scf_guess_pointer = params['FORCE_EVAL']['DFT']['SCF']['SCF_GUESS'] + restart_fname_pointer = params['EXT_RESTART']['RESTART_FILE_NAME'] + + # Also check if they all have the right value + if not (wf_rest_fname_pointer == './parent_calc/aiida-RESTART.wfn' and scf_guess_pointer == 'RESTART' and + restart_fname_pointer == './parent_calc/aiida-1.restart'): + + # If some values are incorrect add them to the input dictionary + params = add_restart_sections(params) + + # If not all the restart keys are present, adding them to the input dictionary + except KeyError: + params = add_restart_sections(params) + + # Might be able to solve the problem + workchain.ctx.inputs.parameters = params # params (new or old ones) that for sure + # include the necessary restart key-value pairs + workchain.report( + "The CP2K calculation wasn't completed. The restart of the calculation might be able to fix the problem.") return ErrorHandlerReport(True, True) + # If the problem is not recoverable if (time_not_exceeded not in content_string or time_exceeded in content_string) and one_step_done not in content_string: - workchain.report("Could NOT fix the problem") - return ErrorHandlerReport(False, True, ExitCode(555)) - workchain.report("No problems!") + workchain.report("It seems that the restart of CP2K calculation wouldn't be able to fix the problem. " + "Sending a signal to stop the Base work chain.") + + # Signaling to the base work chain that the problem could not be recovered. + return ErrorHandlerReport(False, True, ExitCode(1)) + # If everything is alright return None diff --git a/conftest.py b/conftest.py index d98a92f5..a4d01cd7 100644 --- a/conftest.py +++ b/conftest.py @@ -8,4 +8,4 @@ @pytest.fixture(scope='function') def cp2k_code(aiida_local_code_factory): # pylint: disable=unused-argument - return aiida_local_code_factory("cp2k.popt", "cp2k") + return aiida_local_code_factory("cp2k", "cp2k.popt") diff --git a/examples/data/h2o.xyz b/examples/data/h2o.xyz new file mode 100644 index 00000000..b1d04786 --- /dev/null +++ b/examples/data/h2o.xyz @@ -0,0 +1,5 @@ +3 +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" +O 5.0 5.763239 5.596309 +H 5.0 6.526478 5.000000 +H 5.0 5.000000 5.000000 diff --git a/examples/files/GTH_POTENTIALS b/examples/files/GTH_POTENTIALS index 9de02b74..36e4e091 100644 --- a/examples/files/GTH_POTENTIALS +++ b/examples/files/GTH_POTENTIALS @@ -200,3 +200,142 @@ Ar GTH-PADE-q8 GTH-LDA-q8 GTH-PADE GTH-LDA 5.60251627 0.35161921 1 4.97880101 # +################################################################################ +# +# PBE functional +# +################################################################################ +# +H GTH-PBE-q1 GTH-PBE + 1 + 0.20000000 2 -4.17890044 0.72446331 + 0 +# +He GTH-PBE-q2 GTH-PBE + 2 + 0.20000000 2 -9.12214383 1.70270770 + 0 +# +Li GTH-PBE-q3 GTH-PBE + 3 + 0.40000000 4 -14.08115455 9.62621962 -1.78361605 0.08515207 + 0 +# +Be GTH-PBE-q4 GTH-PBE + 4 + 0.32500000 4 -24.06746684 17.27902186 -3.33910629 0.16554912 + 0 +# +B GTH-PBE-q3 GTH-PBE + 2 1 + 0.41899145 2 -5.85946171 0.90375643 + 2 + 0.37132046 1 6.29728018 + 0.36456308 0 +# +C GTH-PBE-q4 GTH-PBE + 2 2 + 0.33847124 2 -8.80367398 1.33921085 + 2 + 0.30257575 1 9.62248665 + 0.29150694 0 +# +N GTH-PBE-q5 GTH-PBE + 2 3 + 0.28379051 2 -12.41522559 1.86809592 + 2 + 0.25540500 1 13.63026257 + 0.24549453 0 +# +O GTH-PBE-q6 GTH-PBE + 2 4 + 0.24455430 2 -16.66721480 2.48731132 + 2 + 0.22095592 1 18.33745811 + 0.21133247 0 +# +F GTH-PBE-q7 GTH-PBE + 2 5 + 0.21492959 2 -21.57302836 3.19977615 + 2 + 0.19468402 1 23.74354045 + 0.18615608 0 +# +Ne GTH-PBE-q8 GTH-PBE + 2 6 + 0.19000000 2 -27.12015973 4.36044962 + 2 + 0.17605938 2 28.17737082 0.83365601 + -1.07624528 + 0.19547452 1 -0.23629360 +# +Na GTH-PBE-q9 GTH-PBE + 3 6 + 0.23652322 2 0.29510499 -0.91388488 + 2 + 0.14356046 1 34.60149228 + 0.12993224 1 -14.27746168 +# +Mg GTH-PBE-q10 GTH-PBE + 4 6 + 0.19275787 2 -20.57539077 3.04016732 + 2 + 0.14140682 1 41.04729209 + 0.10293187 1 -9.98562566 +# +Mg GTH-PBE-q2 + 2 + 0.57696017 1 -2.69040744 + 2 + 0.59392350 2 3.50321099 -0.71677167 + 0.92534825 + 0.70715728 1 0.83115848 +# +Al GTH-PBE-q3 GTH-PBE + 2 1 + 0.45000000 1 -7.55476126 + 2 + 0.48743529 2 6.95993832 -1.88883584 + 2.43847659 + 0.56218949 1 1.86529857 +# +Si GTH-PBE-q4 GTH-PBE + 2 2 + 0.44000000 1 -6.26928833 + 2 + 0.43563383 2 8.95174150 -2.70627082 + 3.49378060 + 0.49794218 1 2.43127673 +# +P GTH-PBE-q5 GTH-PBE + 2 3 + 0.43000000 1 -5.87594327 + 2 + 0.39637742 2 11.00886207 -3.47035607 + 4.48021042 + 0.44829838 1 3.05606416 +# +S GTH-PBE-q6 GTH-PBE + 2 4 + 0.42000000 1 -5.98626038 + 2 + 0.36482035 2 13.14354448 -4.24183045 + 5.47617957 + 0.40948048 1 3.70089057 +# +Cl GTH-PBE-q7 GTH-PBE + 2 5 + 0.41000000 1 -6.39208181 + 2 + 0.33953864 2 15.21898983 -4.93452321 + 6.37044208 + 0.37847416 1 4.33877527 +# +Ar GTH-PBE-q8 GTH-PBE + 2 6 + 0.40000000 1 -7.10000000 + 2 + 0.31881468 2 17.25203807 -5.58548836 + 7.21083447 + 0.35337019 1 4.97421551 +# \ No newline at end of file diff --git a/examples/single_calculations/example_failure.py b/examples/single_calculations/example_failure.py index 1a2630a0..8666968a 100644 --- a/examples/single_calculations/example_failure.py +++ b/examples/single_calculations/example_failure.py @@ -15,11 +15,7 @@ from aiida.orm import (Code, Dict) from aiida.common import NotExistent -from aiida.engine import run -from aiida.common.exceptions import OutputParsingError -from aiida.plugins import CalculationFactory - -Cp2kCalculation = CalculationFactory('cp2k') +from aiida.engine import run_get_node def example_failure(cp2k_code): @@ -33,7 +29,7 @@ def example_failure(cp2k_code): print("Submitted calculation...") # Construct process builder - builder = Cp2kCalculation.get_builder() + builder = cp2k_code.get_builder() builder.parameters = parameters builder.code = cp2k_code builder.metadata.options.resources = { @@ -42,13 +38,13 @@ def example_failure(cp2k_code): } builder.metadata.options.max_wallclock_seconds = 1 * 2 * 60 - try: - run(builder) - print("ERROR!") - print("CP2K failure was not recognized") - sys.exit(3) - except OutputParsingError: + _, calc = run_get_node(builder) + if not calc.is_finished_ok: print("CP2K failure correctly recognized") + return + + print("ERROR!\nCP2K failure was not recognized") + sys.exit(3) @click.command('cli') diff --git a/examples/workchains/example_base.py b/examples/workchains/example_base.py index 1c1a4f67..bbfafad3 100644 --- a/examples/workchains/example_base.py +++ b/examples/workchains/example_base.py @@ -13,9 +13,10 @@ import os import sys -import ase.build import click +import ase.io + from aiida.engine import run from aiida.orm import (Code, Dict, SinglefileData, StructureData) from aiida.common import NotExistent @@ -27,27 +28,25 @@ def example_base(cp2k_code): """Run simple DFT calculation through a workchain""" - pwd = os.path.dirname(os.path.realpath(__file__)) + thisdir = os.path.dirname(os.path.realpath(__file__)) print("Testing CP2K ENERGY on H2O (DFT) through a workchain...") # basis set - basis_file = SinglefileData(file=os.path.join(pwd, "..", "files", "BASIS_MOLOPT")) + basis_file = SinglefileData(file=os.path.join(thisdir, "..", "files", "BASIS_MOLOPT")) # pseudopotentials - pseudo_file = SinglefileData(file=os.path.join(pwd, "..", "files", "GTH_POTENTIALS")) + pseudo_file = SinglefileData(file=os.path.join(thisdir, "..", "files", "GTH_POTENTIALS")) # structure - atoms = ase.build.molecule('H2O') - atoms.center(vacuum=5.0) - structure = StructureData(ase=atoms) + structure = StructureData(ase=ase.io.read(os.path.join(thisdir, '..', 'data', 'h2o.xyz'))) # parameters parameters = Dict( dict={ 'GLOBAL': { 'RUN_TYPE': 'GEO_OPT', - 'WALLTIME': '00:00:30', # too short + 'WALLTIME': '00:30:30', # too short }, 'FORCE_EVAL': { 'METHOD': 'Quickstep', @@ -66,25 +65,21 @@ def example_base(cp2k_code): }, 'XC': { 'XC_FUNCTIONAL': { - '_': 'LDA', + '_': 'PBE', }, }, - 'POISSON': { - 'PERIODIC': 'none', - 'PSOLVER': 'MT', - }, }, 'SUBSYS': { 'KIND': [ { '_': 'O', 'BASIS_SET': 'DZVP-MOLOPT-SR-GTH', - 'POTENTIAL': 'GTH-LDA-q6' + 'POTENTIAL': 'GTH-PBE-q6' }, { '_': 'H', 'BASIS_SET': 'DZVP-MOLOPT-SR-GTH', - 'POTENTIAL': 'GTH-LDA-q1' + 'POTENTIAL': 'GTH-PBE-q1' }, ], },