def test_invariant_under_render(): param = {"KIND": [{"_": "H"}, {"_": "O"}]} Cp2kInput(param).to_string() assert param == {"KIND": [{"_": "H"}, {"_": "O"}]} param = {"SEC": {"_": "H"}} Cp2kInput(param).to_string() assert param == {"SEC": {"_": "H"}}
def test_invariant_under_render(): """Check that the input dictionary is not modified by Cp2kInput.render()""" param = {"KIND": [{"_": "H"}, {"_": "O"}]} Cp2kInput(param).render() assert param == {"KIND": [{"_": "H"}, {"_": "O"}]} param = {"SEC": {"_": "H"}} Cp2kInput(param).render() assert param == {"SEC": {"_": "H"}}
def test_add_keyword_invariant_inp(): """Check that the input dictionary is not modified by add_keyword()""" param = {"FOO": "bar"} inp = Cp2kInput(param) inp.add_keyword("BAR", "boo") assert inp.render() == f"{inp.DISCLAIMER}\nBAR boo\nFOO bar" assert param == {"FOO": "bar"}
def test_add_keyword_invariant_input(): param = {"FOO": "bar"} inp = Cp2kInput(param) inp.add_keyword("BAR", "boo") assert inp.to_string() == "{inp.DISCLAIMER}\nBAR boo\nFOO bar".format( inp=inp) assert param == {"FOO": "bar"}
def test_kinds(): inp = Cp2kInput({"KIND": [{"_": "H"}, {"_": "O"}]}) assert inp.render() == """{inp.DISCLAIMER} &KIND H &END KIND &KIND O &END KIND""".format(inp=inp)
def test_param_iter(): inp = Cp2kInput({ "FORCE_EVAL": [{ "FOO": "bar" }, { "FOO": "baz" }, { "FOO": "boo", "BOO": "hoo" }] }) assert list(inp.param_iter(sections=False)) == [ (("FORCE_EVAL", "FOO"), "bar"), (("FORCE_EVAL", "FOO"), "baz"), (("FORCE_EVAL", "FOO"), "boo"), (("FORCE_EVAL", "BOO"), "hoo"), ] inp = Cp2kInput({"KIND": [{"_": "H"}, {"_": "O"}]}) assert list(inp.param_iter(sections=False)) == [ (("KIND", "_"), "H"), (("KIND", "_"), "O"), ]
def generate_cp2k_input_file(self): from aiida_cp2k.calculations import Cp2kCalculation inp = Cp2kInput(self.input_sets) for i, letter in enumerate('ABC'): inp.add_keyword( 'FORCE_EVAL/SUBSYS/CELL/' + letter, '{:<15} {:<15} {:<15}'.format(*self.structure.cell[i]), override=False, conflicting_keys=['ABC', 'ALPHA_BETA_GAMMA', 'CELL_FILE_NAME']) topo = "FORCE_EVAL/SUBSYS/TOPOLOGY" inp.add_keyword(topo + "/COORD_FILE_NAME", Cp2kCalculation._DEFAULT_COORDS_FILE_NAME, override=False) inp.add_keyword(topo + "/COORD_FILE_FORMAT", "XYZ", override=False, conflicting_keys=['COORDINATE']) return inp.render()
def test_multiple_force_eval(): inp = Cp2kInput( {"FORCE_EVAL": [{ "FOO": "bar" }, { "FOO": "bar" }, { "FOO": "bar" }]}) assert inp.render() == """{inp.DISCLAIMER} &FORCE_EVAL FOO bar &END FORCE_EVAL &FORCE_EVAL FOO bar &END FORCE_EVAL &FORCE_EVAL FOO bar &END FORCE_EVAL""".format(inp=inp)
def test_add_keyword(): inp = Cp2kInput({"FOO": "bar"}) inp.add_keyword("BAR", "boo") assert inp.to_string() == "{inp.DISCLAIMER}\nBAR boo\nFOO bar".format( inp=inp) inp.add_keyword("BOO/BAZ", "boo") assert (inp.to_string() == """{inp.DISCLAIMER} BAR boo &BOO BAZ boo &END BOO FOO bar""".format(inp=inp)) inp.add_keyword(["BOO", "BII"], "boo") assert (inp.to_string() == """{inp.DISCLAIMER} BAR boo &BOO BAZ boo BII boo &END BOO FOO bar""".format(inp=inp))
def test_add_keyword(): """Test add_keyword()""" inp = Cp2kInput({"FOO": "bar"}) inp.add_keyword("BAR", "boo") assert inp.render() == f"{inp.DISCLAIMER}\nBAR boo\nFOO bar" inp.add_keyword("BOO/BAZ", "boo") assert inp.render() == f"""{inp.DISCLAIMER} BAR boo &BOO BAZ boo &END BOO FOO bar""" inp.add_keyword(["BOO", "BII"], "boo") assert inp.render() == f"""{inp.DISCLAIMER} BAR boo &BOO BAZ boo BII boo &END BOO FOO bar""" inp.add_keyword("BOO/BII", "bzzzzzz", override=False) assert inp.render() == f"""{inp.DISCLAIMER} BAR boo &BOO BAZ boo BII boo &END BOO FOO bar""" inp.add_keyword("BOO/BII/BCC", "bcr", override=False) assert inp.render() == f"""{inp.DISCLAIMER} BAR boo &BOO BAZ boo BII boo &END BOO FOO bar""" inp.add_keyword("BOO/BII/BCC", "bcr") assert inp.render() == f"""{inp.DISCLAIMER} BAR boo &BOO BAZ boo &BII BCC bcr &END BII &END BOO FOO bar""" inp.add_keyword("BOO/BII", "boo", override=False) assert inp.render() == f"""{inp.DISCLAIMER} BAR boo &BOO BAZ boo &BII BCC bcr &END BII &END BOO FOO bar""" inp.add_keyword("BOO/BII", "boo", override=True) assert inp.render() == f"""{inp.DISCLAIMER} BAR boo &BOO BAZ boo BII boo &END BOO FOO bar""" inp.add_keyword("BOO/BII", "boo", override=True) assert inp.render() == f"""{inp.DISCLAIMER} BAR boo &BOO BAZ boo BII boo &END BOO FOO bar""" inp.add_keyword("BOO/BIP", "bzz", override=False, conflicting_keys=['BII']) assert inp.render() == f"""{inp.DISCLAIMER} BAR boo &BOO BAZ boo BII boo &END BOO FOO bar""" inp.add_keyword("BOO/BIP", "bzz", override=False, conflicting_keys=[]) assert inp.render() == f"""{inp.DISCLAIMER} BAR boo &BOO BAZ boo BII boo BIP bzz &END BOO FOO bar""" inp.add_keyword("BOO/BEE", "bee", override=True, conflicting_keys=['BAZ', 'BII']) assert inp.render() == f"""{inp.DISCLAIMER}
def test_render_str_val(): inp = Cp2kInput({"FOO": "bar"}) assert inp.render() == f"{inp.DISCLAIMER}\nFOO bar"
def test_invalid_preprocessor(): inp = Cp2kInput({"@SET": "bar"}) with pytest.raises(ValueError): inp.render()
def test_invalid_lowercase_key(): inp = Cp2kInput({"foo": "bar"}) with pytest.raises(ValueError): inp.render()
def test_render_empty(): inp = Cp2kInput() assert inp.to_string() == inp.DISCLAIMER assert inp.params == {}
def test_kinds(): inp = Cp2kInput({"KIND": [{"_": "H"}, {"_": "O"}]}) assert inp.render() == f"""{inp.DISCLAIMER}
def test_multiple_force_eval(): inp = Cp2kInput({"FORCE_EVAL": [{"FOO": "bar"}, {"FOO": "bar"}, {"FOO": "bar"}]}) assert inp.render() == f"""{inp.DISCLAIMER}
def test_render_empty(): inp = Cp2kInput() assert inp.render() == inp.DISCLAIMER
def test_render_str_val(): inp = Cp2kInput({"FOO": "bar"}) assert inp.to_string() == "{inp.DISCLAIMER}\nFOO bar".format(inp=inp) assert inp.params == {"FOO": "bar"}
def test_string_file_equal_output(): params = { "FORCE_EVAL": { "METHOD": "Quickstep", "DFT": { "CHARGE": 0, "KPOINTS": { "SCHEME MONKHORST-PACK": "1 1 1", "SYMMETRY": "OFF", "WAVEFUNCTIONS": "REAL", "FULL_GRID": ".TRUE.", "PARALLEL_GROUP_SIZE": 0, }, "MGRID": {"CUTOFF": 600, "NGRIDS": 4, "REL_CUTOFF": 50}, "UKS": False, "BASIS_SET_FILE_NAME": "BASIS_MOLOPT", "POTENTIAL_FILE_NAME": "GTH_POTENTIALS", "QS": {"METHOD": "GPW", "EXTRAPOLATION": "USE_GUESS"}, "POISSON": {"PERIODIC": "XYZ"}, "SCF": { "EPS_SCF": 1.0e-4, "ADDED_MOS": 1, "SMEAR": {"METHOD": "FERMI_DIRAC", "ELECTRONIC_TEMPERATURE": 300}, "DIAGONALIZATION": {"ALGORITHM": "STANDARD", "EPS_ADAPT": 0.01}, "MIXING": { "METHOD": "BROYDEN_MIXING", "ALPHA": 0.2, "BETA": 1.5, "NBROYDEN": 8, }, }, "XC": {"XC_FUNCTIONAL": {"_": "PBE"}}, "PRINT": { "MO_CUBES": { # this is to print the band gap "STRIDE": "1 1 1", "WRITE_CUBE": "F", "NLUMO": 1, "NHOMO": 1, }, "BAND_STRUCTURE": { "KPOINT_SET": [ { "NPOINTS": 10, "SPECIAL_POINT": ["GAMMA 0.0 0.0 0.0", "X 0.5 0.0 0.5"], "UNITS": "B_VECTOR", }, { "NPOINTS": 10, "SPECIAL_POINT": [ "X 0.5 0.0 0.5", "U 0.625 0.25 0.625", ], "UNITS": "B_VECTOR", }, { "NPOINTS": 10, "SPECIAL_POINT": [ "K 0.375 0.375 0.75", "GAMMA 0.0 0.0 0.0", ], "UNITS": "B_VECTOR", }, { "NPOINTS": 10, "SPECIAL_POINT": ["GAMMA 0.0 0.0 0.0", "L 0.5 0.5 0.5"], "UNITS": "B_VECTOR", }, { "NPOINTS": 10, "SPECIAL_POINT": ["L 0.5 0.5 0.5", "W 0.5 0.25 0.75"], "UNITS": "B_VECTOR", }, { "NPOINTS": 10, "SPECIAL_POINT": ["W 0.5 0.25 0.75", "X 0.5 0.0 0.5"], "UNITS": "B_VECTOR", }, ] }, }, }, "SUBSYS": { "KIND": [ { "_": "Si", "BASIS_SET": "DZVP-MOLOPT-SR-GTH", "POTENTIAL": "GTH-PBE-q4", } ] }, "PRINT": { # this is to print forces (may be necessary for problems # detection) "FORCES": {"_": "ON"} }, }, "GLOBAL": {"EXTENDED_FFT_LENGTHS": True}, # Needed for large systems } inp = Cp2kInput(params) # io.StringIO() is a unicode file-like, similar to a io.open(..., encoding="utf8") with io.StringIO() as fhandle: inp.to_file(fhandle) assert inp.to_string() == fhandle.getvalue()
def prepare_for_submission(self, folder): """Create the input files from the input nodes passed to this instance of the `CalcJob`. :param folder: an `aiida.common.folders.Folder` to temporarily write files on disk :return: `aiida.common.datastructures.CalcInfo` instance """ from aiida_cp2k.utils import Cp2kInput # create cp2k input file inp = Cp2kInput(self.inputs.parameters.get_dict()) inp.add_keyword("GLOBAL/PROJECT", self._DEFAULT_PROJECT_NAME) # create input structure(s) if 'structure' in self.inputs: # As far as I understand self.inputs.structure can't deal with tags # self.inputs.structure.export(folder.get_abs_path(self._DEFAULT_COORDS_FILE_NAME), fileformat="xyz") self._write_structure(self.inputs.structure, folder, self._DEFAULT_COORDS_FILE_NAME) # modify the input dictionary accordingly for i, letter in enumerate('ABC'): inp.add_keyword('FORCE_EVAL/SUBSYS/CELL/' + letter, '{:<15} {:<15} {:<15}'.format( *self.inputs.structure.cell[i]), override=False, conflicting_keys=[ 'ABC', 'ALPHA_BETA_GAMMA', 'CELL_FILE_NAME' ]) topo = "FORCE_EVAL/SUBSYS/TOPOLOGY" inp.add_keyword(topo + "/COORD_FILE_NAME", self._DEFAULT_COORDS_FILE_NAME, override=False) inp.add_keyword(topo + "/COORD_FILE_FORMAT", "XYZ", override=False, conflicting_keys=['COORDINATE']) with io.open(folder.get_abs_path(self._DEFAULT_INPUT_FILE), mode="w", encoding="utf-8") as fobj: try: fobj.write(inp.render()) except ValueError as exc: six.raise_from( InputValidationError( "invalid keys or values in input parameters found"), exc) settings = self.inputs.settings.get_dict( ) if 'settings' in self.inputs else {} # create code info codeinfo = CodeInfo() codeinfo.cmdline_params = settings.pop( 'cmdline', []) + ["-i", self._DEFAULT_INPUT_FILE] codeinfo.stdout_name = self._DEFAULT_OUTPUT_FILE codeinfo.join_files = True codeinfo.code_uuid = self.inputs.code.uuid # create calc info calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.cmdline_params = codeinfo.cmdline_params calcinfo.stdin_name = self._DEFAULT_INPUT_FILE calcinfo.stdout_name = self._DEFAULT_OUTPUT_FILE calcinfo.codes_info = [codeinfo] # files or additional structures if 'file' in self.inputs: calcinfo.local_copy_list = [] for name, obj in self.inputs.file.items(): if isinstance(obj, SinglefileData): calcinfo.local_copy_list.append( (obj.uuid, obj.filename, obj.filename)) elif isinstance(obj, StructureData): self._write_structure(obj, folder, name + '.xyz') calcinfo.retrieve_list = [ self._DEFAULT_OUTPUT_FILE, self._DEFAULT_RESTART_FILE_NAME, self._DEFAULT_TRAJECT_FILE_NAME ] calcinfo.retrieve_list += settings.pop('additional_retrieve_list', []) # symlinks calcinfo.remote_symlink_list = [] calcinfo.remote_copy_list = [] if 'parent_calc_folder' in self.inputs: comp_uuid = self.inputs.parent_calc_folder.computer.uuid remote_path = self.inputs.parent_calc_folder.get_remote_path() copy_info = (comp_uuid, remote_path, self._DEFAULT_PARENT_CALC_FLDR_NAME) if self.inputs.code.computer.uuid == comp_uuid: # if running on the same computer - make a symlink # if not - copy the folder calcinfo.remote_symlink_list.append(copy_info) else: calcinfo.remote_copy_list.append(copy_info) # check for left over settings if settings: raise InputValidationError( "The following keys have been found " + "in the settings input node {}, ".format(self.pk) + "but were not understood: " + ",".join(settings.keys())) return calcinfo