diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..a6cb8b615eb7a44af58c9563596ab6264ef6dbe6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,54 @@ +# use glob syntax. +syntax: glob +*.ser +*.class +*~ +*.bak +#*.off +*.old +*.pyc +*.bk +*.swp +.DS_Store + +# logging files +detailed.log + +# eclipse conf file +.settings +.classpath +.project +.manager +.scala_dependencies + +# idea +.idea +*.iml + +# building +target +build +null +tmp* +temp* +dist +test-output +build.log + +# other scm +.svn +.CVS +.hg* + +# switch to regexp syntax. +# syntax: regexp +# ^\.pc/ + +#SHITTY output not in target directory +build.log + +#emacs TAGS +TAGS + +lib/ +env/ diff --git a/parser/parser-atk/atkio.py b/parser/parser-atk/atkio.py new file mode 100644 index 0000000000000000000000000000000000000000..f293bdef2b42f518095816f0c1080465fcb9c455 --- /dev/null +++ b/parser/parser-atk/atkio.py @@ -0,0 +1,65 @@ +"""Simple wrapper to atk output files""" +from scipy.io.netcdf import netcdf_file + + +class X: + def __init__(self, name=None): + self.name = name + + +class Atoms: + def __init__(self): + self.positions = None + self.numbers = None + self.cell = None + self.pbc = None + + +class Hamiltonian: + def __init__(self): + self.e_entropy = None + self.e_kinetic = None + self.e_total_free = None + self.e_total_extrapolated = None + self.e_xc = None + + +class BandPath: + def __init__(self): + self.labels = None + self.eigenvalues = None + self.kpts = None + + +class WaveFunctions: + def __init__(self): + self.occupations + self.eigenvalues = None + self.ibz_kpts = None + self.band_paths = None + + +class Reader: + def __init__(self, filename): + self.f = netcdf_file(filename) + self.v = self.f.variables + self.read_atoms() + self.read_hamiltonian() + self.read_wave_functions() + + self.xc = None + + def read_atoms(self): + self.atoms = Atoms() + + def read_hamiltonian(self): + self.hamiltonian = Hamiltonian() + + def read_wave_functions(self): + self.wave_functions = WaveFunctions() + + def get_number_of_structures(self): + """ Several structures could in principle be in one file + how many we are dealing with + """ + return 1 diff --git a/parser/parser-atk/libxc_names.py b/parser/parser-atk/libxc_names.py new file mode 100644 index 0000000000000000000000000000000000000000..df65b9f36cf06565181b06c48f0f6fb20ee25caf --- /dev/null +++ b/parser/parser-atk/libxc_names.py @@ -0,0 +1,30 @@ +from __future__ import print_function + +short_names = { + 'LDA': 'LDA_X+LDA_C_PW', + 'PW91': 'GGA_X_PW91+GGA_C_PW91', + 'PBE': 'GGA_X_PBE+GGA_C_PBE', + 'PBEsol': 'GGA_X_PBE_SOL+GGA_C_PBE_SOL', + 'revPBE': 'GGA_X_PBE_R+GGA_C_PBE', + 'RPBE': 'GGA_X_RPBE+GGA_C_PBE', + 'BLYP': 'GGA_X_B88+GGA_C_LYP', + 'HCTH407': 'GGA_XC_HCTH_407', + 'WC': 'GGA_X_WC+GGA_C_PBE', + 'AM05': 'GGA_X_AM05+GGA_C_AM05', + # 'M06-L': 'MGGA_X_M06_L+MGGA_C_M06_L', + # 'TPSS': 'MGGA_X_TPSS+MGGA_C_TPSS', + # 'revTPSS': 'MGGA_X_REVTPSS+MGGA_C_REVTPSS', + 'mBEEF': 'MGGA_X_MBEEF+GGA_C_PBE_SOL'} + + +def get_libxc_name(name): + if name in short_names: + libxc_name = short_names[name] + else: + libxc_name = name + return libxc_name + + +if __name__ == '__main__': + print(get_libxc_name('LDA')) + print(get_libxc_name('GGA_X_PBE')) diff --git a/parser/parser-atk/parser.py b/parser/parser-atk/parser.py new file mode 100644 index 0000000000000000000000000000000000000000..68b167858a429544c228a090fe9004034ac59239 --- /dev/null +++ b/parser/parser-atk/parser.py @@ -0,0 +1,142 @@ +from __future__ import division +import os +from contextlib import contextmanager +import numpy as np +from ase import units +from ase.data import chemical_symbols +from atkio import Reader +from scipy.io.netcdf import netcdf_file +from ase.data import atomic_masses +from ase.units import Rydberg +import setup_paths +from nomadcore.unit_conversion.unit_conversion import convert_unit as cu +from nomadcore.local_meta_info import loadJsonFile, InfoKindEl +from nomadcore.parser_backend import JsonParseEventsWriterBackend +from libxc_names import get_libxc_name + + +@contextmanager +def open_section(p, name): + gid = p.openSection(name) + yield gid + p.closeSection(name, gid) + + +def c(value, unit=None): + """ Dummy function for unit conversion""" + return value + return cu(value, unit) + + +parser_info = {"name": "parser_atk", "version": "1.0"} +path = '../../../../nomad-meta-info/meta_info/nomad_meta_info/' +\ + 'atk.nomadmetainfo.json' +metaInfoPath = os.path.normpath( + os.path.join(os.path.dirname(os.path.abspath(__file__)), path)) + +metaInfoEnv, warns = loadJsonFile(filePath=metaInfoPath, + dependencyLoader=None, + extraArgsHandling=InfoKindEl.ADD_EXTRA_ARGS, + uri=None) + + +def parse(filename): + p = JsonParseEventsWriterBackend(metaInfoEnv) + o = open_section + r = Reader(filename) # Reader(filename) + p.startedParsingSession(filename, parser_info) + with o(p, 'section_run'): + p.addValue('program_name', 'ATK') + p.addValue('program_version', r.version) + mode = parms['mode'] + p.addValue('program_basis_set_type', 'numeric AOs') + with o(p, 'section_basis_set_atom_centered'): + p.addValue('basis_set_atom_centered_short_name', + r.basis) + with o(p, 'section_system') as system_gid: + p.addArrayValues('simulation_cell', + c(r.atoms.cell, 'angstrom')) + symbols = np.array([chemical_symbols[z] for z in r.atoms.numbers]) + p.addArrayValues('atom_labels', symbols) + p.addArrayValues('atom_positions', c(r.atoms.positions, 'angstrom')) + p.addArrayValues('configuration_periodic_dimensions', + np.array(r.atoms.pbc, bool)) + if hasattr(r.atoms, 'momenta'): + masses = atomic_masses[r.atoms.numbers] + velocities = r.atoms.momenta / masses.reshape(-1, 1) + p.addArrayValues('atom_velocities', + c(velocities * units.fs / units.Angstrom, + 'angstrom/femtosecond')) + with o(p, 'section_sampling_method'): + p.addValue('ensemble_type', 'NVE') + with o(p, 'section_frame_sequence'): + pass + with o(p, 'section_method') as method_gid: + p.addValue('relativity_method', 'pseudo_scalar_relativistic') + p.addValue('electronic_structure_method', 'DFT') + p.addValue('scf_threshold_energy_change', + c(r.convergence.scf_energy, 'eV')) # eV / electron + p.addValue('smearing_kind', r.occupations.name) + p.addRealValue('smearing_width', + c(r.occupations.width, 'eV')) + p.addRealValue('total_charge', r.system.charge) + with o(p, 'section_XC_functionals'): + p.addValue('XC_functional_name', + get_libxc_name(r.xc)) + with o(p, 'section_single_configuration_calculation'): + p.addValue('single_configuration_calculation_to_system_ref', + system_gid) + p.addValue('single_configuration_to_calculation_method_ref', + method_gid) + p.addValue('single_configuration_calculation_converged', + r.scf.converged) + p.addRealValue('energy_total', + c(r.hamiltonian.e_total_extrapolated, 'eV')) + p.addRealValue('energy_free', + c(r.hamiltonian.e_total_free, 'eV')) + p.addRealValue('energy_XC', c(r.hamiltonian.e_xc, 'eV')) + p.addRealValue('electronic_kinetic_energy', + c(r.hamiltonian.e_kinetic, 'eV')) + p.addRealValue('energy_correction_entropy', + c(r.hamiltonian.e_entropy, 'eV')) + p.addRealValue('energy_reference_fermi', + c(r.occupations.fermilevel, 'eV')) + p.addRealValue('energy_reference_fermi', + c(r.occupations.fermilevel, 'eV')) + if hasattr(r.results, 'forces'): + p.addArrayValues('atom_forces_free_raw', + c(r.results.forces, 'eV/angstrom')) + #if hasattr(r.results, 'magmoms'): + # p.addArrayValues('x_gpaw_magnetic_moments', + # r.results.magmoms) + # p.addRealValue('x_atk_spin_Sz', r.results.magmoms.sum() / 2.0) + with o(p, 'section_eigenvalues'): + p.addValue('eigenvalues_kind', 'normal') + p.addArrayValues('eigenvalues_values', + c(r.wave_functions.eigenvalues, 'eV')) + p.addArrayValues('eigenvalues_occupation', + r.wave_functions.occupations) + p.addArrayValues('eigenvalues_kpoints', + r.wave_functions.ibz_kpts) + if hasattr(r.wave_functions, 'band_paths'): + with o(p, 'section_k_band'): + for band_path in r.wave_functions.band_paths: + with o(p, 'section_k_band_segment'): + p.addArrayValues('band_energies', + c(band_path.eigenvalues, 'eV')) + p.addArrayValues('band_k_points', 'eV', + band_path.kpoints) + p.addArrayValues('band_segm_labels', + band_path.labels) + p.addArrayValues('band_segm_start_end', + np.asarray( + [band_path.kpoints[0], + band_path.kpoints[-1]])) + + + p.finishedParsingSession("ParseSuccess", None) + +if __name__ == '__main__': + import sys + filename = sys.argv[1] + parse(filename) diff --git a/parser/parser-atk/setup_paths.py b/parser/parser-atk/setup_paths.py new file mode 100644 index 0000000000000000000000000000000000000000..e0a0fb009256a0d4056e81c12e82d15bfd3ea7c4 --- /dev/null +++ b/parser/parser-atk/setup_paths.py @@ -0,0 +1,6 @@ +import sys, os, os.path +baseDir = os.path.dirname(os.path.abspath(__file__)) +commonDir = os.path.normpath(os.path.join(baseDir,"../../../../python-common/common/python")) + +if not commonDir in sys.path: + sys.path.insert(0, commonDir)