Source code for poraque.core.system

# -*- coding: utf-8 -*-
# file: system.py

# This code is part of Poraquê.
# MIT License
#
# Copyright (c) 2026 Leandro Seixas Rocha <leandro.rocha@ilum.cnpem.br> 

import numpy as np

from .units import ANGSTROM, BOHR_TO_ANGSTROM


[docs] class System: """ Represents the physical system (ions, electrons, cell). """ def __init__(self, positions, atomic_numbers, cell, pbc=True, electrons=None, spin_polarized=False): """ Initialize the System. Parameters ---------- positions : array_like Nx3 array of atomic positions. atomic_numbers : array_like Array of atomic numbers (Z). cell : array_like 3x3 array of lattice vectors. pbc : bool or tuple of bool, optional Periodic boundary conditions. electrons : int, optional Total number of electrons. If None, it's inferred from atomic_numbers (neutral). spin_polarized : bool, optional Whether the system is spin-polarized. """ self.positions = np.array(positions, dtype=float) self.atomic_numbers = np.array(atomic_numbers, dtype=int) self.cell = np.array(cell, dtype=float) if isinstance(pbc, bool): self.pbc = (pbc, pbc, pbc) else: self.pbc = tuple(pbc) if electrons is None: self.electrons = int(np.sum(self.atomic_numbers)) else: self.electrons = int(electrons) self.spin_polarized = spin_polarized
[docs] @classmethod def from_ase(cls, atoms, charge=0): """ Create a System object from an ASE ``Atoms`` object. Positions and cell are converted from Ångström (ASE convention) to Bohr (internal atomic units). Parameters ---------- atoms : ase.Atoms The atomic structure. charge : int, optional Net charge; the electron count is ``sum(Z) - charge``. """ numbers = atoms.get_atomic_numbers() return cls( positions=np.asarray(atoms.get_positions()) * ANGSTROM, atomic_numbers=numbers, cell=np.asarray(atoms.get_cell()) * ANGSTROM, pbc=atoms.get_pbc(), electrons=int(np.sum(numbers)) - int(charge), )
[docs] def to_ase(self): """ Export this system to an ASE ``Atoms`` object. Positions and cell are converted from Bohr (internal) back to Ångström (ASE convention). The inverse of :meth:`from_ase` for neutral systems. Returns ------- ase.Atoms The atomic structure in ASE units. """ from ase import Atoms return Atoms( numbers=self.atomic_numbers, positions=self.positions * BOHR_TO_ANGSTROM, cell=self.cell * BOHR_TO_ANGSTROM, pbc=self.pbc, )
def __repr__(self): return f"System(atoms={len(self.atomic_numbers)}, electrons={self.electrons}, spin={self.spin_polarized})"