diff --git a/.github/workflows/python-actions.yaml b/.github/workflows/python-actions.yaml index dbd5aa9..f840c84 100644 --- a/.github/workflows/python-actions.yaml +++ b/.github/workflows/python-actions.yaml @@ -15,10 +15,13 @@ jobs: run: | pip install --upgrade pip pip install .[dev] - pip install types-PyYAML - name: mypy run: | python -m mypy --ignore-missing-imports --follow-imports=silent --no-strict-optional simulationparsers + - name: Test with pytest + run: | + python -m pytest -sv tests + ruff: runs-on: ubuntu-latest diff --git a/pyproject.toml b/pyproject.toml index ca8c1a5..7e6780e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,11 +10,7 @@ readme = "README.md" authors = [{ name = "The NOMAD Authors" }] license = { file = "LICENSE" } dependencies = [ - "lxml==4.7.1", - "pyscf==2.0.1; sys_platform == 'darwin'", - "netCDF4==1.5.4", - "h5py>=3.6.0", - "pyyaml==6.0", + "nomad-schema-plugin-run@git+https://github.com/nomad-coe/nomad-schema-plugin-run.git@develop" ] [project.urls] diff --git a/simulationparsers/utils/__init__.py b/simulationparsers/utils/__init__.py new file mode 100644 index 0000000..d8338f4 --- /dev/null +++ b/simulationparsers/utils/__init__.py @@ -0,0 +1,16 @@ +# Copyright 2018 Markus Scheidgen +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an"AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from .basic_parser import BasicParser + diff --git a/simulationparsers/utils/basic_parser.py b/simulationparsers/utils/basic_parser.py new file mode 100644 index 0000000..2e9d775 --- /dev/null +++ b/simulationparsers/utils/basic_parser.py @@ -0,0 +1,249 @@ +# Copyright 2018 Markus Scheidgen +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an"AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from typing import List +import os +import logging +import numpy as np +import re +from ase.data import chemical_symbols + +from nomad.datamodel import EntryArchive +from nomad.parsing.file_parser import TextParser, Quantity +from runschema.run import Run, Program +from runschema.method import Method +from runschema.system import System, Atoms +from runschema.calculation import ( + Calculation, Energy, EnergyEntry, Forces, ForcesEntry, Thermodynamics) + + +class BasicParser: + ''' + Defines a fairdi parser that parse basic quantities for sections method, system and + single_configuration_calculation. + + Arguments: + code_name: name of the code + units_mapping: dictionary of nomad units for basic quantities such as length + auxiliary_files: re pattern to match auxilliary files from mainfile. If no files + are found will match files in working directory. + kwargs: metainfo_key: re pattern pairs used to parse quantity + ''' + def __init__(self, code_name: str, **kwargs): + self.code_name = code_name + self.units_mapping = kwargs.get('units_mapping', {}) + self.auxilliary_files = kwargs.get('auxilliary_files', '') + self.mainfile_parser = TextParser() + for key, pattern in kwargs.items(): + if isinstance(pattern, str): + self.mainfile_parser._quantities.append( + Quantity(key, pattern, repeats=True, flatten=False)) + elif isinstance(pattern, tuple) and isinstance(pattern[0], str): + self.mainfile_parser._quantities.append( + Quantity(key, pattern[0], str_operation=pattern[1], repeats=True)) + self._re_float = r'\-*\d+\.\d+E*e*\-*\+*\d*' + self.auxilliary_parsers: List[TextParser] = [] + + def init_parser(self): + ''' + Initializes the mainfile and auxiliary parsers. + ''' + self.mainfile_parser.mainfile = self.mainfile + self.mainfile_parser.logger = self.logger + + auxilliary_files = self.mainfile_parser.get('auxilliary_files', os.listdir(self.maindir)) + # remove duplicates, maintain order + auxilliary_files = [f for n, f in enumerate(auxilliary_files) if f not in auxilliary_files[:n]] + self.auxilliary_parsers = [] + for filename in auxilliary_files: + filename = os.path.basename(filename) + if self.mainfile_parser.get('auxilliary_files') is None: + if not self.auxilliary_files or not re.match(self.auxilliary_files, filename): + continue + filename = os.path.join(self.maindir, filename) + if not os.path.isfile(filename): + continue + parser = self.mainfile_parser.copy() + parser.mainfile = filename + parser.logger = self.logger + self.auxilliary_parsers.append(parser) + + def parse(self, mainfile: str, archive: EntryArchive, logger=None, child_archives=None) -> None: + ''' + Triggers parsing of mainfile and writing parsed quantities to archive. + ''' + self.mainfile = os.path.abspath(mainfile) + self.maindir = os.path.dirname(self.mainfile) + self.archive = archive + self.logger = logger if logger is not None else logging + + self.init_parser() + + def set_value(section, key, value, unit=None, shape=None, dtype=None): + dtype = dtype if dtype is not None else type(value) + if value is None: + return + try: + if hasattr(value, 'm_def'): + pass + elif not hasattr(value, 'units'): + value = np.reshape(np.array( + value, dtype=np.dtype(dtype)), shape) if shape is not None else dtype(value) + value = value * unit if unit is not None else value + setattr(section, key, value) + except Exception: + pass + + def get_value(source, pattern, key=None): + if isinstance(source, str): + val = re.findall(pattern, source) + return val[0] if len(val) == 1 else val + elif isinstance(source, list): + return [get_value(s, pattern) for s in source] + elif isinstance(source, dict): + return source.get(key) + else: + return source + + def remove_empty_section(sections, definition): + for n in range(len(sections) - 1, -1, -1): + empty = True + for _, property_def, _, _ in sections[n].m_traverse(): + if property_def is None: + continue + empty = False + break + if empty: + sections[n].m_parent.m_remove_sub_section(definition, n) + + sec_run = Run() + self.archive.run.append(sec_run) + sec_run.program = Program(name=self.code_name) + + energy_unit = self.units_mapping.get('energy', 1.0) + length_unit = self.units_mapping.get('length', 1.0) + mass_unit = self.units_mapping.get('mass') + time_unit = self.units_mapping.get('time') + + re_f = r'\-*\d+\.\d+E*e*\-*\+*\d*' + + for key, values in self.mainfile_parser.items(): + if values is None: + # get if from auxiliary files + values = [] + for parser in self.auxilliary_parsers: + values.extend(parser.get(key, [])) + if values is None or len(values) == 0: + continue + # set header quantities + set_value(sec_run, key, values[0]) + for n, value in enumerate(values): + if len(sec_run.method) <= n: + sec_run.m_create(Method) + sec_method = sec_run.method[n] + + if len(sec_run.system) <= n: + sec_run.m_create(System) + sec_run.system[-1].m_create(Atoms) + sec_system = sec_run.system[n] + + if len(sec_run.calculation) <= n: + sec_run.m_create(Calculation) + sec_run.calculation[-1].m_create(Energy) + sec_run.calculation[-1].m_create(Forces) + sec_run.calculation[-1].m_create(Thermodynamics) + sec_scc = sec_run.calculation[n] + + # method related quantities + if hasattr(Method, key): + set_value(sec_method, key, value) + + # system related quantities + elif hasattr(System, key): + set_value(sec_system, key, value) + + # calculation related quantities + elif hasattr(Calculation, key): + set_value(sec_scc, key, value) + + elif hasattr(Thermodynamics, key): + set_value(sec_scc.thermodynamics, key, value) + + # specific quantities that need formatting + if 'program' in key: + set_value(sec_run.program, key.replace('program_', ''), value) + + if 'energy' in key: + shape = None + val = value[-1] if 'fermi' in key else EnergyEntry(value=value * energy_unit) + sub_key = 'fermi' if 'fermi' in key else key.replace('energy_', '').lower() + set_value(sec_scc.energy, sub_key, val, energy_unit, shape, np.float64) + + if 'atom_forces' in key: + val = get_value(value, rf'.*({re_f}) +({re_f}) +({re_f}).*', 'atom_forces') + if mass_unit is not None and time_unit is not None: + unit = mass_unit * length_unit / time_unit ** 2 + else: + unit = energy_unit / length_unit + sec_scc.forces.total = ForcesEntry() + set_value(sec_scc.forces.total, 'value', val, unit, (np.size(val) // 3, 3), np.float64) + + if 'lattice_vectors' in key: + val = get_value(value, rf'({re_f}) +({re_f}) +({re_f}).*', 'lattice_vectors') + set_value(sec_system.atoms, 'lattice_vectors', val, length_unit, (3, 3), np.float64) + if val is not None: + sec_system.atoms.periodic = [True, True, True] + + if 'atom_positions' in key: + sub_key = 'atom_positions_scaled' if 'atom_positions_scaled' in key else 'atom_positions' + val = get_value(value, rf'({re_f}) +({re_f}) +({re_f}).*', sub_key) + unit = length_unit + if sub_key == 'atom_positions_scaled': + try: + val = np.dot(np.array(val, dtype=np.dtype(np.float64)), sec_system.atoms.lattice_vectors.magnitude) + unit = 1.0 + except Exception: + pass + set_value(sec_system.atoms, 'positions', val, unit, (np.size(val) // 3, 3), np.float64) + + if 'atom_velocities' in key: + val = get_value(value, rf'({re_f}) +({re_f}) +({re_f}).*', 'atom_velocities') + set_value(sec_system.atoms, 'velocities', val, length_unit / time_unit, (np.size(val) // 3, 3), np.float64) + + if 'atom_labels' in key: + val = get_value(value, r'([A-Z][a-z]*)\s', 'atom_labels') + val = [val] if isinstance(val, str) else val + set_value(sec_system.atoms, 'labels', val, shape=(len(val)), dtype=str) + + if 'atom_atom_number' in key: + val = get_value(value, r'(\d+)\s', 'atom_atom_number') + val = [val] if isinstance(val, str) else val + set_value(sec_system.atoms, 'atomic_numbers', val, shape=(len(val)), dtype=np.int32) + set_value(sec_system.atoms, 'labels', [chemical_symbols[int(n)] for n in sec_system.atoms.atomic_numbers], shape=(len(val))) + + # remove unfilled sections + for system in sec_run.system: + if len(system.atoms.values()) == 0: + system.m_remove_sub_section(System.atoms, 0) + for calculation in sec_run.calculation: + if len(calculation.energy.values()) == 0: + calculation.m_remove_sub_section(Calculation.energy, 0) + if len(calculation.forces.values()) == 0: + calculation.m_remove_sub_section(Calculation.forces, 0) + if len(calculation.thermodynamics) > 0 and len(calculation.thermodynamics[0].values()) == 0: + calculation.m_remove_sub_section(Calculation.thermodynamics, 0) + remove_empty_section(sec_run.method, Run.method) + remove_empty_section(sec_run.system, Run.system) + remove_empty_section(sec_run.calculation, Run.calculation) diff --git a/simulationparsers/utils/re_patterns.py b/simulationparsers/utils/re_patterns.py new file mode 100644 index 0000000..1842bbc --- /dev/null +++ b/simulationparsers/utils/re_patterns.py @@ -0,0 +1,20 @@ +# +# Copyright The NOMAD Authors. +# +# This file is part of NOMAD. +# See https://nomad-lab.eu for further info. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +FLOAT = r'[-+]?\d+\.*\d*(?:[Ee][-+]\d+)?' diff --git a/tests/data/onetep/fluor/12-difluoroethane.dat b/tests/data/onetep/fluor/12-difluoroethane.dat new file mode 100644 index 0000000..7009447 --- /dev/null +++ b/tests/data/onetep/fluor/12-difluoroethane.dat @@ -0,0 +1,69 @@ + !============================================================! + ! ~~~~~~~ Quality control test for the ONETEP program ~~~~~~~! + !------------------------------------------------------------! + ! Molecule: 1,2-difluoroethane ! + ! no. of C : 2 ! + ! no. of H : 4 ! + ! no. of F : 2 ! + ! total atoms: 8 ! + !------------------------------------------------------------! + ! Aim: test for Hamiltonian diagonalisation and kernel DIIS. ! + !------------------------------------------------------------! + ! Created by Alvaro Ruiz Serrano on 19/11/2010. ! + !============================================================! + + print_qc : TRUE + output_detail : NORMAL + timings_level : 0 + + task : SINGLEPOINT + + cutoff_energy : 800 eV + kernel_cutoff : 1000 + k_zero : 3.5 + + xc_functional : PBE + dispersion : 1 + + kernel_diis_scheme : dkn_pulay + kernel_diis_threshold: 2.0e-6 + + maxit_pen : 0 + ngwf_threshold_orig : 2.0e-4 + + write_denskern : FALSE + write_tightbox_ngwfs : FALSE + write_xyz : FALSE + + + %block lattice_cart + 24.5 0.0 0.0 + 0.0 24.5 0.0 + 0.0 0.0 24.5 + %endblock lattice_cart + + + %block positions_abs + C 11.03265426 9.90071429 8.78389204 + C 8.44374314 8.72153141 8.78389204 + F 8.17540344 7.00000000 10.78510145 + F 12.50852257 8.97286366 10.78510145 + H 10.90604328 11.96995347 8.99365054 + H 12.00963751 9.43773383 7.00000000 + H 8.09792508 7.68974639 7.00755886 + H 7.00000000 10.20873802 9.02199628 + %endblock positions_abs + + + %block species + C C 6 4 7.0 + F F 9 9 7.0 + H H 1 1 7.0 + %endblock species + + + %block species_pot + H "../../pseudo/hydrogen.recpot" + C "../../pseudo/carbon.recpot" + F "../../pseudo/fluorine.recpot" + %endblock species_pot diff --git a/tests/data/onetep/fluor/12-difluoroethane.out b/tests/data/onetep/fluor/12-difluoroethane.out new file mode 100644 index 0000000..92deb40 --- /dev/null +++ b/tests/data/onetep/fluor/12-difluoroethane.out @@ -0,0 +1,495 @@ + +---------------------------------------------------------------+ + | | + | ####### # # ####### ####### ####### ###### | + | # # ## # # # # # # | + | # # # # # # # # # # | + | # # # # # ##### # ##### ###### | + | # # # # # # # # # | + | # # # ## # # # # | + | ####### # # ####### # ####### # | + | | + | Linear-Scaling Ab Initio Total Energy Program | + | | + | Release for academic collaborators of ODG | + | Version 4.5.3.32 | + | | + +---------------------------------------------------------------+ + | | + | Authors: | + | Jacek Dziedzic, Peter D. Haynes, Nicholas D. M. Hine, | + | Arash. A. Mostofi, Mike C. Payne and Chris-Kriton Skylaris | + | | + | Contributors: | + | J. Aarons, L. Andrinopoulos, P. W. Avraam, R. A. Bell, | + | S. J. Clark, G. C. Constantinescu, F. Corsetti, N. Corsini, | + | O. Dieguez, S. M. M. Dubois, J. M. Escartin, A. Greco, | + | H. H. Helal, Q. O. Hill, L. P. Lee, J.-H. Li, | + | E. B. Linscott, G. Moynihan, D. D. O`Regan, O. K. Okan, | + | M. J. S. Phipps, C. J. Pickard, M. I. J. Probert, | + | L. E. Ratcliff, M. Robinson, A. Ruiz Serrano, J. S. Spencer, | + | E. W. Tait, G. Teobaldi, D. Turban, V. Vitale, | + | K. A. Wilkinson, C. Weber, J. C. Womack | + | and T. J. Zuehlsdorff | + | | + | Copyright (c) 2004-2016 | + | | + | Please cite: | + | "Introducing ONETEP: Linear-scaling density functional | + | simulations on parallel computers". | + | C.-K. Skylaris, P. D. Haynes, A. A. Mostofi, M. C. Payne. | + | J. Chem. Phys. 122 084119 (2005). | + | | + | in all publications arising from your use of ONETEP. | + | | + +---------------------------------------------------------------+ + | | + | ONETEP is based on developments described in the following | + | publications: | + | | + | "Nonorthogonal generalized Wannier function pseudopotential | + | plane-wave method". | + | C.-K. Skylaris, A. A. Mostofi, P. D. Haynes, O. Dieguez, | + | M. C. Payne. | + | Phys. Rev. B 66 035119 (2002). | + | | + | "Preconditioned iterative minimization for linear-scaling | + | electronic structure calculations". | + | A. A. Mostofi, P. D. Haynes, C.-K. Skylaris, M. C. Payne. | + | J. Chem. Phys. 119(17), pp.8842-8848 (2003). | + | | + | "Total-energy calculations on a real space grid with | + | localized functions and a plane-wave basis". | + | A. A. Mostofi, C.-K. Skylaris, P. D. Haynes, M. C. Payne. | + | Comput. Phys. Commun. 147, pp.788-802 (2002). | + | | + | "Accurate kinetic energy evaluation in electronic structure | + | calculations with localized functions on real space grids" | + | C.-K. Skylaris, A. A. Mostofi, P. D. Haynes, C. J. Pickard, | + | M. C. Payne. | + | Comput. Phys. Commun. 140, pp.315-322 (2001). | + | | + | "Accurate ionic forces and geometry optimization in linear- | + | scaling density-functional theory with local orbitals" | + | N. D. M. Hine, M. Robinson, P. D. Haynes, C.-K. Skylaris, | + | M. C. Payne, and A. A. Mostofi. | + | Phys. Rev. B 83 195102 (2011). | + | | + +---------------------------------------------------------------+ + +Job started: 27-09-2016 12:34 (+0100) + +Reading parameters from file "12-difluoroethane.dat" ...... done + +If your calculation crashes here, before "Checking processes and threads..." +is displayed, then your stack size is insufficient. +If so, use "ulimit -s unlimited" at runtime. +You can disable this check with "check_stack_size F". + +Checking processes and threads... + WARNING: Error getting the value of the OMP_NUM_THREADS environment variable. + Not changing the default number of threads (risk of CPU oversubscription). + Default threads: 1 + Running with 4 MPI processes. + There are 4 MPI processes running on the same node as the root process. + Each MPI process is using: + 1 threads for simulation cell FFTs. + 1 threads for parallel FFT box operations. + 1 threads for loops over batched FFT box operations. + 1 threads in other parallel regions. +... done + +Basic input checks...... done + +Reading geometry and species blocks from file "12-difluoroethane.dat" ... + block not found: NGWF initialisation set to SOLVE +... done + + +-------------------------------------------------------------------------------- +---------------------------------- INPUT FILE ---------------------------------- +-------------------------------------------------------------------------------- + +print_qc : TRUE +output_detail : NORMAL +timings_level : 0 +task : SINGLEPOINT +cutoff_energy : 800 eV +kernel_cutoff : 1000 +k_zero : 3.5 +xc_functional : PBE +dispersion : 1 +kernel_diis_scheme : dkn_pulay +kernel_diis_threshold: 2.0e-6 +maxit_pen : 0 +ngwf_threshold_orig : 2.0e-4 +write_denskern : FALSE +write_tightbox_ngwfs : FALSE +write_xyz : FALSE +%block lattice_cart +24.5 0.0 0.0 +0.0 24.5 0.0 +0.0 0.0 24.5 +%endblock lattice_cart +%block positions_abs + Hash = -000007963062986021238501 +%endblock positions_abs +%block species +C C 6 4 7.0 +F F 9 9 7.0 +H H 1 1 7.0 +%endblock species +%block species_pot +H "../../pseudo/hydrogen.recpot" +C "../../pseudo/carbon.recpot" +F "../../pseudo/fluorine.recpot" +%endblock species_pot + +-------------------------------------------------------------------------------- +-------------------------------- END INPUT FILE -------------------------------- +-------------------------------------------------------------------------------- + + + + ESDF WARNING(1): "kernelcutoff" (esdf_physical) has no units. Assume "bohr". + ESDF WARNING(2): "kzero" (esdf_physical) has no units. Assume "1/bohr". +WARNING in pseudopotentials_read_species: string "LDA" found in pseudopotential +file "../../pseudo/fluorine.recpot", yet xc_functional = "PBE". + +<<<<<<<<<<<<<<<<<<<<<<<<< Pseudopotential information >>>>>>>>>>>>>>>>>>>>>>>>>> +File: ../../pseudo/carbon.recpot [ 2001 points up to Gmax= 52.9 (1/bohr)] + Atomic number: 6; ionic charge: 4.000000 + Shell 1: l = 0; rc = 1.48 bohr +File: ../../pseudo/fluorine.recpot [ 2001 points up to Gmax= 52.9 (1/bohr)] + Atomic number: 9; ionic charge: 7.000000 + Shell 1: l = 0; rc = 1.60 bohr +File: ../../pseudo/hydrogen.recpot [ 2001 points up to Gmax= 52.9 (1/bohr)] + Atomic number: 1; ionic charge: 1.000000 + Local potential +<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +-------------------------- Atom counting information --------------------------- +Symbol Natoms Nngwfs Nprojs + C 2 8 2 + F 2 18 2 + H 4 4 0 +....... ...... ...... ...... +Totals: 8 30 4 +-------------------------------------------------------------------------------- + +=============================== PSINC grid sizes =============================== + Simulation cell: 49 x 49 x 49 + FFT-box: 49 x 49 x 49 + PPD: 7 x 7 x 1 +Grid space d1= 0.500000000000a0 (KE cutoff= 30.38533Eh = 826.82697eV) +Grid space d2= 0.500000000000a0 (KE cutoff= 30.38533Eh = 826.82697eV) +Grid space d3= 0.500000000000a0 (KE cutoff= 30.38533Eh = 826.82697eV) +================================================================================ + +********************* Fourier parallelisation information ********************** + Coarse grid (whole simulation cell) dimensions: 49 49 49 + Real-space ('12') slabs/node (min max mean): 12 13 12 + Recip-space ('23') slabs/node (min max mean): 6 7 6 +******************************************************************************** + +********************* Fourier parallelisation information ********************** + Double grid (whole simulation cell) dimensions: 98 98 98 + Real-space ('12') slabs/node (min max mean): 24 25 24 + Recip-space ('23') slabs/node (min max mean): 12 13 12 +******************************************************************************** + +Atom SCF Calculation for C : Z (AE atom) = 6 : Z (PS atom) = 4 +Config String: +Orbitals (num,occ): 2 2.00 2.00 +Orbitals (num,l): 2 0 1 +Atom SCF converged after 21 iterations to a total energy of -5.38688250 + +Atom SCF Calculation for F : Z (AE atom) = 9 : Z (PS atom) = 7 +Config String: +Orbitals (num,occ): 5 2.00 5.00 0.00 0.00 0.00 +Orbitals (num,l): 5 0 1 0 1 2 +Atom SCF converged after 28 iterations to a total energy of -24.17124726 + +WARNING in ngwfs_initialise: Setting radial NGWF functions for species 2 (F): +Last NGWF on atom has m = -2 and does not complete set of m-values for l = 2. +This breaks symmetry and may cause unstable NGWF optimisation and poor +convergence. Suggest increasing number of NGWFs per atom from 9 to 13. +NB: All NGWF radial function angular momenta: 0 1 0 1 2 + + +Atom SCF Calculation for H : Z (AE atom) = 1 : Z (PS atom) = 1 +Config String: +Orbitals (num,occ): 1 1.00 +Orbitals (num,l): 1 0 +Atom SCF converged after 26 iterations to a total energy of -0.45392390 + +Determining parallel strategy ...... done +Calculating Ewald energy ... 35.913065 Hartree +Model : Elstner +Dispersion Correction Energy: -0.61292798E-03 Hartree +Basis initialisation ...... done +Sparse matrix initialisation ... done +NGWF initialisation ...... done +Up spin density kernel initialisation ...... done + +>>> Optimising kernel for current NGWFs: + +------------------ Hamiltonian diagonalisation + kernel DIIS ------------------- + +-------------------------------------------------------------------------------- + Iter Spin Resid. Commut. H-L Gap DGap Energy DEnergy +@ 1 1 3.5E-01 0.0E+00 2.515E-01 2.5E-01 -61.96772866341010 -6.2E+01 +@ 2 1 2.6E-01 0.0E+00 2.627E-01 1.1E-02 -62.00590696765417 -3.8E-02 +@ 3 1 1.9E-01 0.0E+00 2.702E-01 7.5E-03 -62.02421072518696 -1.8E-02 +@ 4 1 1.4E-01 0.0E+00 2.753E-01 5.1E-03 -62.03329004950061 -9.1E-03 +@ 5 1 1.1E-01 0.0E+00 2.788E-01 3.5E-03 -62.03790096367098 -4.6E-03 +@ 6 1 8.2E-02 0.0E+00 2.812E-01 2.4E-03 -62.04028343139357 -2.4E-03 +@ 7 1 1.4E-03 0.0E+00 2.875E-01 6.3E-03 -62.04297371267694 -2.7E-03 +@ 8 1 3.5E-04 0.0E+00 2.876E-01 1.2E-04 -62.04297519639009 -1.5E-06 +@ 9 1 3.1E-04 0.0E+00 2.876E-01 1.7E-05 -62.04297521396437 -1.8E-08 +@ 10 1 2.8E-04 0.0E+00 2.876E-01 6.8E-07 -62.04297521521158 -1.2E-09 +@ 11 1 2.4E-04 0.0E+00 2.876E-01 -1.2E-06 -62.04297521563454 -4.2E-10 +@ 12 1 1.3E-04 0.0E+00 2.876E-01 -1.7E-06 -62.04297521532864 3.1E-10 +@ 13 1 1.1E-04 0.0E+00 2.876E-01 -4.7E-06 -62.04297521204359 3.3E-09 +@ 14 1 2.1E-05 0.0E+00 2.876E-01 9.0E-06 -62.04297521604418 -4.0E-09 +@ 15 1 5.9E-06 0.0E+00 2.876E-01 3.3E-07 -62.04297521606254 -1.8E-11 +@ 16 1 2.1E-06 0.0E+00 2.876E-01 -7.1E-07 -62.04297521607664 -1.4E-11 +@ 17 1 1.2E-07 0.0E+00 2.876E-01 1.7E-07 -62.04297521607971 -3.1E-12 + +@CONVERGED1 : calculation converged after 17 iterations. + + [total_energy]: -62.042975216080 + [deltaE]: -0.000000000003 + [HKS,SKH(1)]: 0.000000000000 + [K,KSK(1)]: 0.000000000000 + [residual(1)]: 0.000000115671 + [mu(1)]: -0.568183550426 + [max(denskern)(1)]: 1.008361536893 + [max(ham)(1)]: 1.068546925724 + + +>>> Density kernel optimised for the current NGWF basis: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Total energy = -6.20429752160797E+01 Eh + [H,K] commutator = 5.7710E-09 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + +################################################################################ +########################### NGWF CG iteration 001 ############################# +################################################################################ + +>>> Checking for convergence of NGWFs: NOT CONVERGED + ======================================================================== + NGWF RMS gradient = 1.5095E-03 > 2.0000E-04 | above tolerance + ======================================================================== + +>>> Improving NGWFs using line search: + ======================================================================== + Predicted total energy = -6.23174098124076E+01 Eh + Predicted gain in energy = -2.74434596327943E-01 Eh + ======================================================================== + + +>>> Optimising kernel for current NGWFs: + +------------------ Hamiltonian diagonalisation + kernel DIIS ------------------- + +-------------------------------------------------------------------------------- + Iter Spin Resid. Commut. H-L Gap DGap Energy DEnergy +@ 1 1 1.0E-01 0.0E+00 3.098E-01 2.2E-02 -62.31690842124750 -2.7E-01 +@ 2 1 8.3E-02 0.0E+00 3.087E-01 -1.2E-03 -62.31871242423301 -1.8E-03 +@ 3 1 6.6E-02 0.0E+00 3.077E-01 -9.5E-04 -62.31972087464113 -1.0E-03 +@ 4 1 5.4E-02 0.0E+00 3.070E-01 -7.5E-04 -62.32028237004770 -5.6E-04 +@ 5 1 4.5E-02 0.0E+00 3.064E-01 -5.8E-04 -62.32059439778605 -3.1E-04 +@ 6 1 3.7E-02 0.0E+00 3.060E-01 -4.5E-04 -62.32076778613285 -1.7E-04 +@ 7 1 3.0E-04 0.0E+00 3.046E-01 -1.4E-03 -62.32099119371093 -2.2E-04 +@ 8 1 1.5E-04 0.0E+00 3.046E-01 2.1E-06 -62.32099120173832 -8.0E-09 +@ 9 1 1.1E-04 0.0E+00 3.046E-01 2.0E-06 -62.32099120448893 -2.8E-09 +@ 10 1 5.4E-05 0.0E+00 3.046E-01 1.5E-06 -62.32099120590181 -1.4E-09 +@ 11 1 3.5E-05 0.0E+00 3.046E-01 4.8E-07 -62.32099120601292 -1.1E-10 +@ 12 1 2.4E-05 0.0E+00 3.046E-01 4.8E-07 -62.32099120586797 1.4E-10 +@ 13 1 2.3E-05 0.0E+00 3.046E-01 -8.5E-08 -62.32099120590778 -4.0E-11 +@ 14 1 6.1E-07 0.0E+00 3.046E-01 -1.2E-06 -62.32099120609475 -1.9E-10 + +@CONVERGED2 : calculation converged after 14 iterations. + + [total_energy]: -62.320991206095 + [deltaE]: -0.000000000187 + [HKS,SKH(1)]: 0.000000000000 + [K,KSK(1)]: 0.000000000000 + [residual(1)]: 0.000000609541 + [mu(1)]: -0.546156251471 + [max(denskern)(1)]: 0.987275870179 + [max(ham)(1)]: 1.051741197244 + + +>>> Density kernel optimised for the current NGWF basis: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Total energy = -6.23209912060948E+01 Eh + [H,K] commutator = 3.7484E-08 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + +################################################################################ +########################### NGWF CG iteration 002 ############################# +################################################################################ + +>>> Checking for convergence of NGWFs: NOT CONVERGED + ======================================================================== + NGWF RMS gradient = 6.3438E-04 > 2.0000E-04 | above tolerance + ======================================================================== + +>>> Improving NGWFs using line search: + ======================================================================== + Predicted total energy = -6.23819045271485E+01 Eh + Predicted gain in energy = -6.09133210537678E-02 Eh + ======================================================================== + + +>>> Optimising kernel for current NGWFs: + +------------------ Hamiltonian diagonalisation + kernel DIIS ------------------- + +-------------------------------------------------------------------------------- + Iter Spin Resid. Commut. H-L Gap DGap Energy DEnergy +@ 1 1 7.3E-02 0.0E+00 3.007E-01 -3.9E-03 -62.38080814011222 -6.0E-02 +@ 2 1 5.6E-02 0.0E+00 3.002E-01 -4.8E-04 -62.38201742142157 -1.2E-03 +@ 3 1 4.4E-02 0.0E+00 2.998E-01 -4.1E-04 -62.38269036332674 -6.7E-04 +@ 4 1 3.4E-02 0.0E+00 2.994E-01 -3.3E-04 -62.38306333185025 -3.7E-04 +@ 5 1 2.7E-02 0.0E+00 2.992E-01 -2.5E-04 -62.38326950239842 -2.1E-04 +@ 6 1 2.2E-02 0.0E+00 2.990E-01 -1.9E-04 -62.38338330968504 -1.1E-04 +@ 7 1 1.0E-04 0.0E+00 2.986E-01 -4.1E-04 -62.38352473264382 -1.4E-04 +@ 8 1 4.2E-05 0.0E+00 2.986E-01 2.0E-06 -62.38352473529898 -2.7E-09 +@ 9 1 3.2E-05 0.0E+00 2.986E-01 1.7E-07 -62.38352473540289 -1.0E-10 +@ 10 1 2.5E-05 0.0E+00 2.986E-01 -4.8E-08 -62.38352473551271 -1.1E-10 +@ 11 1 1.8E-05 0.0E+00 2.986E-01 2.0E-07 -62.38352473559954 -8.7E-11 +@ 12 1 7.8E-06 0.0E+00 2.986E-01 4.1E-07 -62.38352473562737 -2.8E-11 +@ 13 1 7.1E-06 0.0E+00 2.986E-01 1.3E-08 -62.38352473562367 3.7E-12 +@ 14 1 4.6E-07 0.0E+00 2.986E-01 -2.5E-07 -62.38352473564195 -1.8E-11 + +@CONVERGED3 : calculation converged after 14 iterations. + + [total_energy]: -62.383524735642 + [deltaE]: -0.000000000018 + [HKS,SKH(1)]: 0.000000000000 + [K,KSK(1)]: 0.000000000000 + [residual(1)]: 0.000000463481 + [mu(1)]: -0.531727421612 + [max(denskern)(1)]: 0.982313897517 + [max(ham)(1)]: 1.046856712127 + + +>>> Density kernel optimised for the current NGWF basis: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Total energy = -6.23835247356419E+01 Eh + [H,K] commutator = 1.2219E-08 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + +################################################################################ +########################### NGWF CG iteration 003 ############################# +################################################################################ + +>>> Checking for convergence of NGWFs: NOT CONVERGED + ======================================================================== + NGWF RMS gradient = 2.7222E-04 > 2.0000E-04 | above tolerance + ======================================================================== + +>>> Improving NGWFs using line search: + ======================================================================== + Predicted total energy = -6.23942579667293E+01 Eh + Predicted gain in energy = -1.07332310873431E-02 Eh + ======================================================================== + + +>>> Optimising kernel for current NGWFs: + +------------------ Hamiltonian diagonalisation + kernel DIIS ------------------- + +-------------------------------------------------------------------------------- + Iter Spin Resid. Commut. H-L Gap DGap Energy DEnergy +@ 1 1 2.7E-02 0.0E+00 2.926E-01 -6.0E-03 -62.39402686147427 -1.1E-02 +@ 2 1 2.0E-02 0.0E+00 2.924E-01 -2.3E-04 -62.39421218685935 -1.9E-04 +@ 3 1 1.6E-02 0.0E+00 2.922E-01 -1.8E-04 -62.39431429613455 -1.0E-04 +@ 4 1 1.2E-02 0.0E+00 2.921E-01 -1.3E-04 -62.39437049383171 -5.6E-05 +@ 5 1 9.8E-03 0.0E+00 2.920E-01 -9.7E-05 -62.39440141361177 -3.1E-05 +@ 6 1 8.0E-03 0.0E+00 2.919E-01 -7.1E-05 -62.39441843347667 -1.7E-05 +@ 7 1 3.3E-05 0.0E+00 2.918E-01 -1.3E-04 -62.39443961441583 -2.1E-05 +@ 8 1 1.6E-05 0.0E+00 2.918E-01 -4.4E-07 -62.39443961474928 -3.3E-10 +@ 9 1 8.8E-06 0.0E+00 2.918E-01 3.5E-07 -62.39443961481859 -6.9E-11 +@ 10 1 4.1E-06 0.0E+00 2.918E-01 1.9E-07 -62.39443961484833 -3.0E-11 +@ 11 1 2.7E-06 0.0E+00 2.918E-01 2.2E-08 -62.39443961485284 -4.5E-12 +@ 12 1 1.5E-06 0.0E+00 2.918E-01 4.4E-08 -62.39443961485479 -1.9E-12 + +@CONVERGED4 : calculation converged after 12 iterations. + + [total_energy]: -62.394439614855 + [deltaE]: -0.000000000002 + [HKS,SKH(1)]: 0.000000000000 + [K,KSK(1)]: 0.000000000000 + [residual(1)]: 0.000001524802 + [mu(1)]: -0.527789252089 + [max(denskern)(1)]: 0.982363990396 + [max(ham)(1)]: 1.045144416780 + + +>>> Density kernel optimised for the current NGWF basis: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Total energy = -6.23944396148548E+01 Eh + [H,K] commutator = 9.1645E-08 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + + +################################################################################ +########################### NGWF CG iteration 004 ############################# +################################################################################ + +>>> Checking for convergence of NGWFs: + ........................................................ + | *** NGWF optimisation converged *** | + | RMS NGWF gradient = 0.00014145961773 | + | Criteria satisfied: | + | -> RMS NGWF gradient lower than set threshold. | + ======================================================== + +================================================================================ + ---------------- ENERGY COMPONENTS (Eh) ---------------- + | Kinetic : 43.56625646880812 | + | Pseudopotential (local) : -224.85183693469443 | + | Pseudo (non-coul chg cor) : 0.00000000000000 + | Pseudopotential (non-local): 8.40224578259678 | + | Hartree : 88.82709748311089 | + | Exchange-correlation : -14.25065412072763 | + | Ewald : 35.91306463402832 | + | Dispersion Correction : -0.00061292797685 | + | Total : -62.39443961485481 | + -------------------------------------------------------- + Integrated density : 25.99999999999982 +================================================================================ + + + <<<<< CALCULATION SUMMARY >>>>> +|ITER| RMS GRADIENT | TOTAL ENERGY | step | Epredicted + 0 0.00150945962378 -62.04297521607971 0.700605 -62.31740981240765 + 1 0.00063438479673 -62.32099120609475 0.869082 -62.38190452714852 + 2 0.00027222129411 -62.38352473564195 0.818478 -62.39425796672928 + 3 0.00014145961773 -62.39443961485479 <-- CG + + [NGWF iterations]: 4 + [total_energy]: -62.394439614855 + [rms_gradient]: 0.000141459618 + +------------------------------ TIMING INFORMATION ------------------------------ +AVERAGE TIME: 120.970s on 4 node(s) +TOTAL TIME: 120.971s on 4 node(s) + +Job completed: 27-09-2016 12:36 (+0100) + diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..b6ee20c --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,44 @@ +# Copyright 2018 Markus Scheidgen +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an"AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pytest +import numpy as np + +from nomad.units import ureg +from nomad.datamodel import EntryArchive +from simulationparsers.utils import BasicParser + +class TestBasicParser: + @pytest.fixture(scope='class') + def onetep_parser(self): + re_f = r'\-*\d+\.\d+E*\-*\+*\d+' + return BasicParser( + 'ONETEP', + units_mapping=dict(energy=ureg.hartree, length=ureg.bohr), + auxilliary_files=r'([\w\-]+\.dat)', + program_version=r'Version\s*([\d\.]+)', + lattice_vectors=r'\%block lattice_cart\s*([\s\S]+?)\%endblock lattice_cart', + atom_labels_atom_positions=rf'\%block positions\_abs\s*(\w+\s+{re_f}\s+{re_f}\s+{re_f}[\s\S]+?)\%endblock positions\_abs', + XC_functional=r'xc\_functional\s*\:\s*(\w+)', + energy_total=rf'Total energy\s*=\s*({re_f})\s*Eh') + + def test_onetep_parser(self, onetep_parser): + archive = EntryArchive() + onetep_parser.parse('tests/data/onetep/fluor/12-difluoroethane.out', archive, None) + + assert archive.run[0].program.version == '4.5.3.32' + assert len(archive.run[0].calculation) == 4 + sec_system = archive.run[0].system[0] + assert sec_system.atoms.labels[7] == 'H' + assert np.shape(sec_system.atoms.positions) == (8, 3)