Skip to content

kups.observables.stress

Stress tensor calculations via the virial theorem.

Stress is the symmetric (3, 3) tensor

σ = -1/V sym[Σ_i r_i ⊗ ∂U/∂r_i + h^T · ∂U/∂h]

Only the 6 lower-triangular entries of ∂U/∂h are stored (the cell's parameter DoF; see :class:kups.core.cell.TriclinicFrame). For lower-triangular h, the lower triangle of h^T · ∂U/∂h depends only on the lower triangle of ∂U/∂h: since h[k, i] = 0 for k < i, the sum (h^T·g)[i, j] = Σ_{k≥i} h[k, i]·g[k, j] for j ≤ i touches only g[k, j] with k ≥ i ≥ j, i.e. lower-triangular entries. The upper triangle of σ is filled by symmetry — the full 3×3 cell virial is never materialized.

IsMolecularVirialParticles

Bases: HasPositions, HasGroupIndex, HasSystemIndex, Protocol

Particles with position gradients, group and system assignment.

Source code in src/kups/observables/stress.py
@runtime_checkable
class IsMolecularVirialParticles(HasPositions, HasGroupIndex, HasSystemIndex, Protocol):
    """Particles with position gradients, group and system assignment."""

    @property
    def position_gradients(self) -> Array: ...

IsMolecularVirialState

Bases: IsState[IsMolecularVirialParticles, IsVirialSystems], Protocol

State with groups for molecular virial stress.

Source code in src/kups/observables/stress.py
class IsMolecularVirialState(
    IsState[IsMolecularVirialParticles, IsVirialSystems], Protocol
):
    """State with groups for molecular virial stress."""

    @property
    def groups(self) -> Table[GroupId, HasSystemIndex]: ...

IsVirialParticles

Bases: HasPositions, HasSystemIndex, Protocol

Particles with position gradients ∂U/∂r.

Source code in src/kups/observables/stress.py
@runtime_checkable
class IsVirialParticles(HasPositions, HasSystemIndex, Protocol):
    """Particles with position gradients ∂U/∂r."""

    @property
    def position_gradients(self) -> Array: ...

IsVirialSystems

Bases: HasCell[Periodic3D], Protocol

Systems with cell gradients ∂U/∂h (stored lower-triangular).

Source code in src/kups/observables/stress.py
@runtime_checkable
class IsVirialSystems(HasCell[Periodic3D], Protocol):
    """Systems with cell gradients ∂U/∂h (stored lower-triangular)."""

    @property
    def cell_gradients(self) -> Cell[Periodic3D]: ...

molecular_stress_via_virial_theorem(particles, groups, systems)

Compute molecular virial stress tensor (RASPA convention).

Parameters:

Name Type Description Default
particles Table[ParticleId, IsMolecularVirialParticles]

Per-particle positions, group/system index, and gradients.

required
groups Table[GroupId, HasSystemIndex]

Per-group system assignment.

required
systems Table[SystemId, IsVirialSystems]

Per-system cell and cell gradients (lower-triangular).

required

Returns:

Type Description
Table[SystemId, Array]

Symmetric stress tensor per system, shape (n_systems, 3, 3).

Source code in src/kups/observables/stress.py
def molecular_stress_via_virial_theorem(
    particles: Table[ParticleId, IsMolecularVirialParticles],
    groups: Table[GroupId, HasSystemIndex],
    systems: Table[SystemId, IsVirialSystems],
) -> Table[SystemId, Array]:
    """Compute molecular virial stress tensor (RASPA convention).

    Args:
        particles: Per-particle positions, group/system index, and gradients.
        groups: Per-group system assignment.
        systems: Per-system cell and cell gradients (lower-triangular).

    Returns:
        Symmetric stress tensor per system, shape ``(n_systems, 3, 3)``.
    """
    group_cells = systems[groups.data.system].cell
    stress = _molecular_stress_via_virial_theorem(
        particles.data.position_gradients,
        systems.data.cell_gradients.vectors,
        particles.data.positions,
        particles.data.group,
        group_cells,
        particles.data.system,
        systems.data.cell.vectors,
        systems.data.cell.volume,
    )
    return Table(systems.keys, stress)

molecular_virial_stress_from_state(key, state)

Compute molecular virial stress from a state.

Source code in src/kups/observables/stress.py
def molecular_virial_stress_from_state(
    key: Array, state: IsMolecularVirialState
) -> Table[SystemId, Array]:
    """Compute molecular virial stress from a state."""
    del key
    return molecular_stress_via_virial_theorem(
        state.particles, state.groups, state.systems
    )

stress_via_virial_theorem(particles, systems)

Compute atomic-level virial stress tensor.

Parameters:

Name Type Description Default
particles Table[ParticleId, IsVirialParticles]

Per-particle positions, system index, and position gradients.

required
systems Table[SystemId, IsVirialSystems]

Per-system cell and cell gradients (lower-triangular).

required

Returns:

Type Description
Table[SystemId, Array]

Symmetric stress tensor per system, shape (n_systems, 3, 3).

Source code in src/kups/observables/stress.py
def stress_via_virial_theorem(
    particles: Table[ParticleId, IsVirialParticles],
    systems: Table[SystemId, IsVirialSystems],
) -> Table[SystemId, Array]:
    """Compute atomic-level virial stress tensor.

    Args:
        particles: Per-particle positions, system index, and position gradients.
        systems: Per-system cell and cell gradients (lower-triangular).

    Returns:
        Symmetric stress tensor per system, shape ``(n_systems, 3, 3)``.
    """
    stress = _stress_via_virial_theorem(
        particles.data.position_gradients,
        systems.data.cell_gradients.vectors,
        particles.data.positions,
        systems.data.cell.vectors,
        particles.data.system,
    )
    return Table(systems.keys, stress)

virial_stress_from_state(key, state)

Compute atomic virial stress from a state.

Source code in src/kups/observables/stress.py
def virial_stress_from_state(
    key: Array, state: IsState[IsVirialParticles, IsVirialSystems]
) -> Table[SystemId, Array]:
    """Compute atomic virial stress from a state."""
    del key
    return stress_via_virial_theorem(state.particles, state.systems)