Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python interface for MSG #71

Merged
merged 5 commits into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ build-python:
install-python:
python -m pip install uv maturin
maturin develop --release --manifest-path moyopy/Cargo.toml
python -m uv pip install -e "moyopy[dev]"
python -m pip install -e "moyopy[dev]"
pre-commit install

test-python:
Expand Down
10 changes: 9 additions & 1 deletion moyo/src/base/lattice.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use nalgebra::base::{Matrix3, Vector3};
use nalgebra::base::{Matrix3, OMatrix, RowVector3, Vector3};
use serde::{Deserialize, Serialize};

use crate::math::{
Expand All @@ -22,6 +22,14 @@ impl Lattice {
}
}

pub fn from_basis(basis: [[f64; 3]; 3]) -> Self {
Self::new(OMatrix::from_rows(&[
RowVector3::from(basis[0]),
RowVector3::from(basis[1]),
RowVector3::from(basis[2]),
]))
}

/// Return Minkowski reduced lattice and transformation matrix to it
pub fn minkowski_reduce(&self) -> Result<(Self, Matrix3<i32>), MoyoError> {
let (reduced_basis, trans_mat) = minkowski_reduce(&self.basis);
Expand Down
4 changes: 2 additions & 2 deletions moyo/src/base/magnetic_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub trait MagneticMoment: Sized + Clone {
}
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Collinear(pub f64);

impl MagneticMoment for Collinear {
Expand Down Expand Up @@ -66,7 +66,7 @@ impl MagneticMoment for Collinear {
}
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NonCollinear(pub Vector3<f64>);

impl MagneticMoment for NonCollinear {
Expand Down
3 changes: 2 additions & 1 deletion moyo/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ pub use hall_symbol::{HallSymbol, MagneticHallSymbol};
pub use hall_symbol_database::{hall_symbol_entry, HallNumber, HallSymbolEntry, Number};
pub use magnetic_hall_symbol_database::{magnetic_hall_symbol_entry, MagneticHallSymbolEntry};
pub use magnetic_space_group::{
get_magnetic_space_group_type, ConstructType, UNINumber, NUM_MAGNETIC_SPACE_GROUP_TYPES,
get_magnetic_space_group_type, ConstructType, MagneticSpaceGroupType, UNINumber,
NUM_MAGNETIC_SPACE_GROUP_TYPES,
};
pub use setting::Setting;

Expand Down
5 changes: 5 additions & 0 deletions moyo/src/data/magnetic_space_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,17 @@ pub enum ConstructType {

#[derive(Debug, Clone)]
pub struct MagneticSpaceGroupType {
/// Serial number of UNI (and BNS) symbols
pub uni_number: UNINumber,
/// Serial number in Litvin's [Magnetic group tables](https://www.iucr.org/publ/978-0-9553602-2-0)
pub litvin_number: i32,
/// BNS number e.g. '151.32'
pub bns_number: &'static str,
/// OG number e.g. '153.4.1270'
pub og_number: &'static str,
/// ITA number for reference space group in BNS setting
pub number: Number,
/// Construct type of magnetic space group
pub construct_type: ConstructType,
}

Expand Down
32 changes: 26 additions & 6 deletions moyo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@ moyo = "*"
The basic usage of **moyo** is to create a [`moyo::base::Cell`](Cell) representing a crystal structure, and then create a [`moyo::MoyoDataset`](MoyoDataset) from the [`moyo::base::Cell`](Cell).
The [`moyo::MoyoDataset`](MoyoDataset) contains symmetry information of the input crystal structure: for example, the space group number, symmetry operations, and standardized cell.

Magnetic symmetry is also supported in **moyo**.
Magnetic moments are represented by a struct implementing the [`moyo::base::MagneticMoment`](MagneticMoment) trait: for example, [`moyo::base::Collinear`](Collinear) or [`moyo::base::NonCollinear`](NonCollinear).
Magnetic cell is represented by a [`moyo::base::MagneticCell`](MagneticCell) struct.
The [`moyo::MoyoMagneticDataset`](MoyoMagneticDataset) contains magnetic symmetry information of the input magnetic cell: for example, the magnetic space-group type, magnetic symmetry operations, and standardized magnetic cell.

```
use nalgebra::{matrix, vector, Matrix3, Vector3};
use moyo::MoyoDataset;
use moyo::base::{Cell, AngleTolerance, Lattice};
use moyo::{MoyoDataset, MoyoMagneticDataset};
use moyo::base::{Cell, MagneticCell, AngleTolerance, Lattice, NonCollinear, RotationMagneticMomentAction};
use moyo::data::Setting;

let lattice = Lattice::new(matrix![
Expand All @@ -39,15 +44,29 @@ let positions = vec![
Vector3::new(x_4f + 0.5, -x_4f + 0.5, 0.5), // O(4f)
];
let numbers = vec![0, 0, 1, 1, 1, 1];
let cell = Cell::new(lattice, positions, numbers);
let cell = Cell::new(lattice.clone(), positions.clone(), numbers.clone());

let symprec = 1e-5;
let symprec = 1e-4;
let angle_tolerance = AngleTolerance::Default;
let setting = Setting::Standard;

let dataset = MoyoDataset::new(&cell, symprec, angle_tolerance, setting).unwrap();

assert_eq!(dataset.number, 136); // P4_2/mnm

let magnetic_moments = vec![
NonCollinear(vector![0.0, 0.0, 0.7]),
NonCollinear(vector![0.0, 0.0, -0.7]),
NonCollinear(vector![0.0, 0.0, 0.0]),
NonCollinear(vector![0.0, 0.0, 0.0]),
NonCollinear(vector![0.0, 0.0, 0.0]),
NonCollinear(vector![0.0, 0.0, 0.0]),
];
let magnetic_cell = MagneticCell::new(lattice, positions, numbers, magnetic_moments);

let action = RotationMagneticMomentAction::Axial;

let magnetic_dataset = MoyoMagneticDataset::new(&magnetic_cell, symprec, angle_tolerance, None, action).unwrap();
assert_eq!(magnetic_dataset.uni_number, 1159); // BNS 136.499
```

## Features
Expand All @@ -57,6 +76,7 @@ assert_eq!(dataset.number, 136); // P4_2/mnm
- Space-group type identification
- Wyckoff position assignment
- Crystal structure symmetrization
- Magnetic space group support

*/
#[allow(unused_imports)]
Expand Down Expand Up @@ -90,7 +110,7 @@ use nalgebra::Matrix3;
/// A dataset containing symmetry information of the input crystal structure.
pub struct MoyoDataset {
// ------------------------------------------------------------------------
// Space-group type
// Identification
// ------------------------------------------------------------------------
/// Space group number.
pub number: Number,
Expand Down
2 changes: 1 addition & 1 deletion moyo/src/symmetrize/magnetic_standardize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ impl<M: MagneticMoment> StandardizedMagneticCell<M> {
action,
);
let prim_std_mag_cell =
MagneticCell::from_cell(ref_std_cell.cell.clone(), prim_std_magnetic_moments);
MagneticCell::from_cell(ref_std_cell.prim_cell.clone(), prim_std_magnetic_moments);

// To (conventional) standardized magnetic cell
let refined_prim_mag_cell = ref_std_cell
Expand Down
2 changes: 1 addition & 1 deletion moyopy/examples/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
numbers = [0, 0, 1, 1]
cell = moyopy.Cell(basis, positions, numbers)

dataset = moyopy.MoyoDataset(cell, symprec=1e-5, angle_tolerance=None, setting=None)
dataset = moyopy.MoyoDataset(cell, symprec=1e-4, angle_tolerance=None, setting=None)
assert dataset.number == 186
assert dataset.hall_number == 480

Expand Down
2 changes: 1 addition & 1 deletion moyopy/examples/pymatgen_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class MoyoSpacegroupAnalyzer:
def __init__(
self,
structure: Structure,
symprec: float = 1e-5,
symprec: float = 1e-4,
angle_tolerance: float | None = None,
setting: moyopy.Setting | None = None,
):
Expand Down
57 changes: 57 additions & 0 deletions moyopy/python/moyopy/_base.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,52 @@ class Cell:
def positions(self) -> list[list[float]]: ...
@property
def numbers(self) -> list[int]: ...
@property
def num_atoms(self) -> int: ...
def serialize_json(self) -> str: ...
@classmethod
def deserialize_json(cls, json_str: str) -> Cell: ...

class CollinearMagneticCell:
def __init__(
self,
basis: list[list[float]],
positions: list[list[float]],
numbers: list[int],
magnetic_moments: list[float],
): ...
@property
def basis(self) -> list[list[float]]: ...
@property
def positions(self) -> list[list[float]]: ...
@property
def numbers(self) -> list[int]: ...
@property
def magnetic_moments(self) -> list[float]: ...
@property
def num_atoms(self) -> int: ...
def serialize_json(self) -> str: ...
@classmethod
def deserialize_json(cls, json_str: str) -> Cell: ...

class NonCollinearMagneticCell:
def __init__(
self,
basis: list[list[float]],
positions: list[list[float]],
numbers: list[int],
magnetic_moments: list[list[float]],
): ...
@property
def basis(self) -> list[list[float]]: ...
@property
def positions(self) -> list[list[float]]: ...
@property
def numbers(self) -> list[int]: ...
@property
def magnetic_moments(self) -> list[list[float]]: ...
@property
def num_atoms(self) -> int: ...
def serialize_json(self) -> str: ...
@classmethod
def deserialize_json(cls, json_str: str) -> Cell: ...
Expand All @@ -23,3 +69,14 @@ class Operations:
@property
def num_operations(self) -> int: ...
def __len__(self) -> int: ...

class MagneticOperations:
@property
def rotations(self) -> list[list[list[float]]]: ...
@property
def translations(self) -> list[list[float]]: ...
@property
def time_reversals(self) -> list[bool]: ...
@property
def num_operations(self) -> int: ...
def __len__(self) -> int: ...
22 changes: 22 additions & 0 deletions moyopy/python/moyopy/_data.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,26 @@ class SpaceGroupType:
for string values.
"""

class MagneticSpaceGroupType:
"""Magnetic space-group type information."""
def __init__(self, uni_number: int): ...
@property
def uni_number(self) -> int:
"""Serial number of UNI (and BNS) symbols."""
@property
def litvin_number(self) -> int:
"""Serial number in Litvin's `Magnetic group tables <https://www.iucr.org/publ/978-0-9553602-2-0>`_."""
@property
def bns_number(self) -> str:
"""BNS number e.g. '151.32'"""
@property
def og_number(self) -> str:
"""OG number e.g. '153.4.1270'"""
@property
def number(self) -> int:
"""ITA number for reference space group in BNS setting."""
@property
def construct_type(self) -> int:
"""Construct type of magnetic space group from 1 to 4."""

def operations_from_number(number: int, setting: Setting) -> Operations: ...
Loading
Loading