diff --git a/dependencies/parsers/elastic b/dependencies/parsers/elastic index 1c1dacfde7328e8ec9ca49419fae7d56157d9479..2b9ee49d74cf89bb07e2b798e6e391fd5ac724c6 160000 --- a/dependencies/parsers/elastic +++ b/dependencies/parsers/elastic @@ -1 +1 @@ -Subproject commit 1c1dacfde7328e8ec9ca49419fae7d56157d9479 +Subproject commit 2b9ee49d74cf89bb07e2b798e6e391fd5ac724c6 diff --git a/dependencies/parsers/lammps b/dependencies/parsers/lammps index 3e4eb8aac2cf46882569e3823669f894c6890885..84602c2c62462b93274dab91fce38a72b249cb49 160000 --- a/dependencies/parsers/lammps +++ b/dependencies/parsers/lammps @@ -1 +1 @@ -Subproject commit 3e4eb8aac2cf46882569e3823669f894c6890885 +Subproject commit 84602c2c62462b93274dab91fce38a72b249cb49 diff --git a/nomad/datamodel/metainfo/public.py b/nomad/datamodel/metainfo/public.py index ee6eeb157452f17f198f64d8c58538a17413f839..e24adfbab979e13a93ff3b1351bb8194e621158e 100644 --- a/nomad/datamodel/metainfo/public.py +++ b/nomad/datamodel/metainfo/public.py @@ -1607,6 +1607,32 @@ class section_energy_van_der_Waals(MSection): a_legacy=LegacyDefinition(name='energy_van_der_Waals')) +class section_energy_contribution(MSection): + ''' + Section describing the contributions to the total energy. + ''' + + m_def = Section(validate=False, a_legacy=LegacyDefinition(name='section_energy_contribution')) + + energy_contibution_kind = Quantity( + type=str, + shape=[], + description=''' + The kind of the energy contribution. Can be one of bond, pair, coulomb, etc. + ''', + a_legacy=LegacyDefinition(name='energy_contibution_kind')) + + energy_contribution_value = Quantity( + type=np.dtype(np.float64), + shape=[], + unit='joule', + description=''' + Value of the energy contribution. + ''', + categories=[energy_component, energy_value], + a_legacy=LegacyDefinition(name='energy_contribution_value')) + + class section_frame_sequence_user_quantity(MSection): ''' Section collecting some user-defined quantities evaluated along a sequence of frame. @@ -4460,6 +4486,42 @@ class section_single_configuration_calculation(MSection): ''', a_legacy=LegacyDefinition(name='zero_point_method')) + enthalpy = Quantity( + type=np.dtype(np.float64), + shape=[], + unit='joule', + description=''' + Value of the calculated enthalpy i.e. energy_total + pressure * volume. + ''', + categories=[energy_component, energy_value], + a_legacy=LegacyDefinition(name='energy_enthalpy')) + + pressure = Quantity( + type=np.dtype(np.float64), + shape=[], + unit='pascal', + description=''' + Value of the pressure of the system. + ''', + a_legacy=LegacyDefinition(name='pressure')) + + temperature = Quantity( + type=np.dtype(np.float64), + shape=[], + unit='kelvin', + description=''' + Value of the temperature of the system. + ''', + a_legacy=LegacyDefinition(name='temperature')) + + time_step = Quantity( + type=int, + shape=[], + description=''' + The number of time steps with respect to the start of the calculation. + ''', + a_legacy=LegacyDefinition(name='time_step')) + section_atom_projected_dos = SubSection( sub_section=SectionProxy('section_atom_projected_dos'), repeats=True, @@ -4505,6 +4567,11 @@ class section_single_configuration_calculation(MSection): repeats=True, a_legacy=LegacyDefinition(name='section_energy_van_der_Waals')) + section_energy_contribution = SubSection( + sub_section=SectionProxy('section_energy_contribution'), + repeats=True, + a_legacy=LegacyDefinition(name='section_energy_contribution')) + section_k_band_normalized = SubSection( sub_section=SectionProxy('section_k_band_normalized'), repeats=True, @@ -5771,6 +5838,41 @@ class Elastic(MSection): a_legacy=LegacyDefinition(name='strain_maximum')) +class MolecularDynamics(MSection): + ''' + Section containing results of molecular dynamics workflow. + ''' + + m_def = Section( + validate=False, a_legacy=LegacyDefinition(name='section_molecular_dynamics')) + + finished_normally = Quantity( + type=bool, + shape=[], + description=''' + Indicates if calculation terminated normally. + ''', + a_legacy=LegacyDefinition(name='finished_normally')) + + with_trajectory = Quantity( + type=bool, + shape=[], + description=''' + Indicates if calculation includes trajectory data. + ''', + a_legacy=LegacyDefinition(name='with_trajectory'), + a_search=Search()) + + with_thermodynamics = Quantity( + type=bool, + shape=[], + description=''' + Indicates if calculation contains thermodynamic data. + ''', + a_legacy=LegacyDefinition(name='with_thermodynamics'), + a_search=Search()) + + class Workflow(MSection): ''' Section containing the results of a workflow. @@ -5802,5 +5904,9 @@ class Workflow(MSection): sub_section=SectionProxy('Elastic'), a_legacy=LegacyDefinition(name='section_elastic')) + section_molecular_dynamics = SubSection( + sub_section=SectionProxy('MolecularDynamics'), + a_legacy=LegacyDefinition(name='section_molecular_dynamics')) + m_package.__init_metainfo__() diff --git a/nomad/parsing/parsers.py b/nomad/parsing/parsers.py index 04f843b685e97f24829f97f0001684d2d4260565..cb34990c95bb969c74fe9db1cfd6ed8a8b3e3050 100644 --- a/nomad/parsing/parsers.py +++ b/nomad/parsing/parsers.py @@ -27,6 +27,7 @@ from aptfimparser import APTFIMParser from vaspparser import VASPParser from phonopyparser import PhonopyParser from elasticparser import ElasticParser +from lammpsparser import LammpsParser try: # these packages are not available without parsing extra, which is ok, if the @@ -378,11 +379,7 @@ parsers = [ parser_class_name='tinkerparser.TinkerParser', mainfile_contents_re=r'TINKER --- Software Tools for Molecular Design' ), - LegacyParser( - name='parsers/lammps', code_name='lammps', domain='dft', - parser_class_name='lammpsparser.LammpsParser', - mainfile_contents_re=r'^LAMMPS' - ), + LammpsParser(), LegacyParser( name='parsers/amber', code_name='Amber', domain='dft', parser_class_name='amberparser.AMBERParser', diff --git a/nomad/parsing/text_parser.py b/nomad/parsing/text_parser.py index 47d0dbe9d66dcf5b37851e347433bd3d8685e79e..c1caabd37467234775d9226e298bf4b9db3f2903 100644 --- a/nomad/parsing/text_parser.py +++ b/nomad/parsing/text_parser.py @@ -20,7 +20,7 @@ import logging class Quantity: - def __init__(self, name, re_pattern, str_operation=None, unit=None, dtype=None): + def __init__(self, name, re_pattern, str_operation=None, unit=None, dtype=None, comment=None): self.name = name self.re_pattern = re.compile(re_pattern.encode()) self.unit = unit @@ -28,6 +28,7 @@ class Quantity: self.dtype = dtype self._value = None self._str_operation = str_operation + self._comment = comment @property def value(self): @@ -37,6 +38,10 @@ class Quantity: def value(self, val_in): def convert_value(val): + if self._comment is not None: + if val.strip()[0] == self._comment: + return + if self._str_operation is not None: val = self._str_operation(val) @@ -44,36 +49,44 @@ class Quantity: val = val.strip().split() if isinstance(val, str) else val val = val[0] if len(val) == 1 else val - def _get_dtype(val): - dtype = type(val) - + def _convert(val): if isinstance(val, str): if self.dtype is None: if val.isdecimal(): - self.dtype = int + val = int(val) else: try: - float(val) - self.dtype = float + val = float(val) except Exception: - self.dtype = str + pass self.shape = [] - return self.dtype + return val + + elif type(val) in [np.ndarray, list]: + try: + dtype = float if self.dtype is None else self.dtype + val = np.array(val, dtype=dtype) + self.dtype = dtype + if np.all(np.mod(val, 1) == 0): + val = np.array(val, dtype=int) + self.dtype = int + self.shape = list(np.shape(val)) + + except Exception: + val = [_convert(v) for v in val] + self.dtype = None - elif dtype in (np.ndarray, list, tuple): - if len(val) > 0: - _get_dtype(val[-1]) - self.shape = list(np.shape(val)) - return lambda x: np.array(x, dtype=self.dtype) + return val else: self.dtype = type(val) self.shape = [] - return self.dtype + return val + + val = _convert(val) - dtype = _get_dtype(val) - return dtype(val) + return val self._value = None if val_in is None else [convert_value(val) for val in val_in] @@ -149,7 +162,7 @@ class UnstructuredTextFileParser: if key is None or quantity.name in key: value = [] for res in quantity.re_pattern.finditer(self.file_mmap): - value.append(''.join([group.decode() for group in res.groups()])) + value.append(''.join([group.decode() for group in res.groups() if group])) if not value: continue