Skip to content

Commit

Permalink
initial investigation into harmonizing particles and atoms
Browse files Browse the repository at this point in the history
  • Loading branch information
jrudz committed Dec 4, 2024
1 parent 243cbb6 commit e9e830a
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 33 deletions.
16 changes: 15 additions & 1 deletion src/nomad_simulations/schema_packages/atoms_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,17 @@ def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
)


class AtomsState(Entity):
class State(Entity):
"""
A base section to define the state information of the system.
"""

def __init__(self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs):
super().__init__(m_def, m_context, **kwargs)
self.labels = None


class AtomsState(State):
"""
A base section to define each atom state information.
"""
Expand Down Expand Up @@ -641,3 +651,7 @@ def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
self.chemical_symbol = self.resolve_chemical_symbol(logger=logger)
if self.atomic_number is None:
self.atomic_number = self.resolve_atomic_number(logger=logger)

# Set the labels
if self.chemical_symbol is not None:
self.labels = self.chemical_symbol
58 changes: 35 additions & 23 deletions src/nomad_simulations/schema_packages/general.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
from typing import TYPE_CHECKING
#! TODO: Why is TYPE_CHECKING False?
from typing import TYPE_CHECKING, List, Iterable, Union

if TYPE_CHECKING:
from collections.abc import Callable

from nomad.datamodel.datamodel import EntryArchive
from structlog.stdlib import BoundLogger
if not TYPE_CHECKING:
from nomad.datamodel.datamodel import (
EntryArchive,
)
from nomad.metainfo import (
Context,
Section,
)
from structlog.stdlib import (
BoundLogger,
)

import numpy as np
from nomad.config import config
Expand Down Expand Up @@ -227,7 +234,7 @@ def resolve_composition_formula(self, system_parent: ModelSystem) -> None:
"""

def set_composition_formula(
system: ModelSystem, subsystems: list[ModelSystem], atom_labels: list[str]
system: ModelSystem, subsystems: list[ModelSystem], labels: list[str]
) -> None:
"""Determine the composition formula for `system` based on its `subsystems`.
If `system` has no children, the atom_labels are used to determine the formula.
Expand All @@ -243,8 +250,8 @@ def set_composition_formula(
system.atom_indices if system.atom_indices is not None else []
)
subsystem_labels = (
[np.array(atom_labels)[atom_indices]]
if atom_labels
[np.array(labels)[atom_indices]]
if labels
else ['Unknown' for atom in range(len(atom_indices))]
)
else:
Expand All @@ -259,7 +266,7 @@ def set_composition_formula(
children_names=subsystem_labels
)

def get_composition_recurs(system: ModelSystem, atom_labels: list[str]) -> None:
def get_composition_recurs(system: ModelSystem, labels: list[str]) -> None:
"""Traverse the system hierarchy downward and set the branch composition for
all (sub)systems at each level.
Expand All @@ -269,23 +276,28 @@ def get_composition_recurs(system: ModelSystem, atom_labels: list[str]) -> None:
to the atom indices stored in system.
"""
subsystems = system.model_system
set_composition_formula(
system=system, subsystems=subsystems, atom_labels=atom_labels
)
set_composition_formula(system=system, subsystems=subsystems, labels=labels)
if subsystems:
for subsystem in subsystems:
get_composition_recurs(system=subsystem, atom_labels=atom_labels)
get_composition_recurs(system=subsystem, labels=labels)

# ! CG: system_parent.cell[0].particles_state instead of atoms_state!
atoms_state = (
system_parent.cell[0].atoms_state if system_parent.cell is not None else []
)
atom_labels = (
[atom.chemical_symbol for atom in atoms_state]
if atoms_state is not None
else []
)
get_composition_recurs(system=system_parent, atom_labels=atom_labels)
labels = []
if system_parent.cell is not None:
if system_parent.cell[0].name == 'AtomicCell':
labels = (
[atom.labels for atom in system_parent.cell[0].atoms_state]
if system_parent.cell[0].atoms_state is not None
else []
)
elif system_parent.cell[0].name == 'ParticleCell':
labels = (
[atom.labels for atom in system_parent.cell[0].particles_state]
if system_parent.cell[0].particles_state is not None
else []
)

get_composition_recurs(system=system_parent, labels=labels)

def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
super(Schema, self).normalize(archive, logger)
Expand Down
16 changes: 9 additions & 7 deletions src/nomad_simulations/schema_packages/model_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -1372,10 +1372,12 @@ def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:

#! ChemicalFormula calls `ase_atoms = atomic_cell.to_ase_atoms(logger=logger)` and `ase_atoms.get_chemical_formula()`
# Creating and normalizing ChemicalFormula section
# TODO add support for fractional formulas (possibly add `AtomicCell.concentrations` for each species)
sec_chemical_formula = self.m_create(ChemicalFormula)
sec_chemical_formula.normalize(archive, logger)
if sec_chemical_formula.m_cache:
self.elemental_composition = sec_chemical_formula.m_cache.get(
'elemental_composition', []
)
if any(cell.name == 'AtomicCell' for cell in self.cell):
# TODO: get_sibling_section() may need to be updated to more specifically search for AtomicCell in ChemicalFormula and Symmetry, in cases where multiple different cells are present
# TODO add support for fractional formulas (possibly add `AtomicCell.concentrations` for each species)
sec_chemical_formula = self.m_create(ChemicalFormula)
sec_chemical_formula.normalize(archive, logger)
if sec_chemical_formula.m_cache:
self.elemental_composition = sec_chemical_formula.m_cache.get(
'elemental_composition', []
)
10 changes: 8 additions & 2 deletions src/nomad_simulations/schema_packages/particles_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import ase.geometry
import numpy as np
import pint
from deprecated import deprecated

# from deprecated import deprecated
from nomad.datamodel.data import ArchiveSection
from nomad.datamodel.metainfo.annotations import ELNAnnotation
from nomad.datamodel.metainfo.basesections import Entity
Expand All @@ -17,6 +18,8 @@
from nomad.metainfo import Context, Section
from structlog.stdlib import BoundLogger

from nomad_simulations.schema_packages.atoms_state import State


class Particles:
"""Particle object.
Expand Down Expand Up @@ -424,7 +427,7 @@ def _set_positions(self, pos):


# ? How generic (usable for any CG model) vs. Martini-specific do we want to be?
class ParticlesState(Entity):
class ParticlesState(State):
"""
A base section to define individual coarse-grained (CG) particle information.
"""
Expand Down Expand Up @@ -491,3 +494,6 @@ def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
# Get particle_type as string, if possible.
if not isinstance(self.particle_type, str):
self.particle_type = self.resolve_particle_type(logger=logger)

if self.particle_type is not None:
self.labels = self.particle_type

1 comment on commit e9e830a

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/nomad_simulations
   __init__.py4250%3–4
   _version.py11282%5–6
src/nomad_simulations/schema_packages
   __init__.py15287%39–41
   atoms_state.py1962189%13–15, 201–204, 228, 283–284, 352–353, 355, 537, 549–550, 621–625, 640–644, 651
   basis_set.py2402888%8–9, 122–133, 172–185, 208, 391–395, 417–418, 462–465, 584, 615, 617
   general.py93792%128, 192, 293–294, 309–310, 320
   model_method.py2697871%10–12, 171–174, 177–184, 276–277, 297, 318–339, 355–381, 384–401, 587, 780, 791, 833–840, 878, 897, 977, 1034, 1109, 1223
   model_system.py4007781%45–51, 236, 255, 259, 262, 265, 291, 378–379, 456–457, 474–475, 585–587, 630–639, 653–684, 695–712, 715–718, 850–853, 900–907, 1081–1082, 1306–1310, 1316–1317, 1325–1326, 1331, 1355
   numerical_settings.py2596176%12–14, 217, 219–220, 223–226, 230–231, 238–241, 250–253, 257–260, 262–265, 270–273, 279–282, 469–496, 571, 606–609, 633, 636, 681, 683–686, 690, 694, 741, 745–766, 821–822, 889
   outputs.py1201092%9–10, 252–255, 295–298, 323, 325, 362, 381
   particles_state.py986138%17–19, 145–222, 281, 300–311, 318–323, 328, 332, 336, 340, 345–350, 363–368, 383–393, 397, 409–412, 416, 420, 484–489, 492–499
   physical_property.py102793%20–22, 202, 331–333
   variables.py861286%8–10, 98, 121, 145, 167, 189, 211, 233, 256, 276
src/nomad_simulations/schema_packages/properties
   band_gap.py51590%8–10, 135–136
   band_structure.py1232580%9–11, 232–265, 278, 285, 321–322, 325, 372–373, 378
   energies.py42979%7–9, 36, 57, 82, 103, 119, 134
   fermi_surface.py17476%7–9, 40
   forces.py22673%7–9, 36, 56, 79
   greens_function.py991387%7–9, 210–211, 214, 235–236, 239, 260–261, 264, 400
   hopping_matrix.py29583%7–9, 58, 94
   permittivity.py48883%7–9, 97–105
   spectral_profile.py26012851%9–11, 57–60, 95–98, 199–300, 356–368, 393–396, 416, 421–424, 466–502, 526, 573–576, 592–593, 598–604
   thermodynamics.py752764%7–9, 35, 56, 72, 81, 90, 101, 110, 137, 147, 157, 172–174, 177, 193, 213–215, 218, 234, 254–256, 259
src/nomad_simulations/schema_packages/utils
   utils.py791680%8–11, 65–74, 83–84, 89, 92, 169–170
TOTAL274961478% 

Tests Skipped Failures Errors Time
402 0 💤 4 ❌ 0 🔥 6.795s ⏱️

Please sign in to comment.