From 66cbcafc34114be00b24388d6927276706823673 Mon Sep 17 00:00:00 2001 From: bpuchala Date: Tue, 10 Oct 2023 15:49:30 -0400 Subject: [PATCH] do not allow automatic conversion from floating point to integer arrays --- python/src/xtal.cpp | 22 ++++---- python/tests/test_siteindexconverter.py | 15 +++++ python/tests/test_structure.py | 61 +++++++++++++++++++++ python/tests/test_unitcellindexconverter.py | 15 +++++ 4 files changed, 103 insertions(+), 10 deletions(-) diff --git a/python/src/xtal.cpp b/python/src/xtal.cpp index ce1aff1..222e2e5 100644 --- a/python/src/xtal.cpp +++ b/python/src/xtal.cpp @@ -804,7 +804,7 @@ xtal::SimpleStructure make_simplestructure_within( } xtal::SimpleStructure make_superstructure( - Eigen::Matrix3l const &transformation_matrix_to_super, + Eigen::Ref transformation_matrix_to_super, xtal::SimpleStructure const &simple) { return xtal::make_superstructure(transformation_matrix_to_super.cast(), simple); @@ -2549,7 +2549,8 @@ PYBIND11_MODULE(_xtal, m) { "Equivalent to :func:`~casm.xtal.make_structure_within`"); m.def("make_superstructure", &make_superstructure, - py::arg("transformation_matrix_to_super"), py::arg("structure"), + py::arg("transformation_matrix_to_super").noconvert(), + py::arg("structure"), R"pbdoc( Make a superstructure @@ -3010,7 +3011,7 @@ PYBIND11_MODULE(_xtal, m) { self += xtal::UnitCell(translation); return self; }, - py::arg("translation"), + py::arg("translation").noconvert(), "Translates the integral site coordinate by adding unit cell indices") .def( "__add__", @@ -3018,7 +3019,7 @@ PYBIND11_MODULE(_xtal, m) { Eigen::Vector3l const &translation) { return self + xtal::UnitCell(translation); }, - py::arg("translation"), + py::arg("translation").noconvert(), "Translates the integral site coordinate by adding unit cell indices") .def( "__isub__", @@ -3026,7 +3027,7 @@ PYBIND11_MODULE(_xtal, m) { self -= xtal::UnitCell(translation); return self; }, - py::arg("translation"), + py::arg("translation").noconvert(), "Translates the integral site coordinate by subtracting unit cell " "indices") .def( @@ -3035,7 +3036,7 @@ PYBIND11_MODULE(_xtal, m) { Eigen::Vector3l const &translation) { return self - xtal::UnitCell(translation); }, - py::arg("translation"), + py::arg("translation").noconvert(), "Translates the integral site coordinate by subtracting unit cell " "indices") .def( @@ -3125,7 +3126,8 @@ PYBIND11_MODULE(_xtal, m) { Convert between integral site indices :math:`(b,i,j,k)` and linear site index :math:`l`. )pbdoc") .def(py::init(), - py::arg("transformation_matrix_to_super"), py::arg("n_sublattice"), + py::arg("transformation_matrix_to_super").noconvert(), + py::arg("n_sublattice"), R"pbdoc( Parameters @@ -3182,7 +3184,7 @@ PYBIND11_MODULE(_xtal, m) { For each supercell, CASM generates an ordering of lattice sites :math:`(i,j,k)`. )pbdoc") .def(py::init(), - py::arg("transformation_matrix_to_super"), + py::arg("transformation_matrix_to_super").noconvert(), R"pbdoc( Parameters @@ -3214,7 +3216,7 @@ PYBIND11_MODULE(_xtal, m) { R"pbdoc( Bring the given :class:`~libcasm.xtal.IntegralSiteCoordinate` into the superlattice using superlattice translations. )pbdoc", - py::arg("unitcell")) + py::arg("unitcell").noconvert()) .def( "linear_unitcell_index", [](xtal::UnitCellIndexConverter const &f, @@ -3222,7 +3224,7 @@ PYBIND11_MODULE(_xtal, m) { R"pbdoc( Given unitcell indices, :math:`(i,j,k)`, retreive the corresponding linear unitcell index. By default, if :func:`~libcasm.xtal.IntegralSiteCoordinateConverter.never_bring_within` has not been called, the lattice point is brought within the superlattice using superlattice translations. )pbdoc", - py::arg("unitcell")) + py::arg("unitcell").noconvert()) .def( "unitcell", [](xtal::UnitCellIndexConverter const &f, diff --git a/python/tests/test_siteindexconverter.py b/python/tests/test_siteindexconverter.py index b2ce541..b344994 100644 --- a/python/tests/test_siteindexconverter.py +++ b/python/tests/test_siteindexconverter.py @@ -73,3 +73,18 @@ def bijk(b, i, j, k): f.never_bring_within() f.always_bring_within() assert f.linear_site_index(bijk(0, 2, 2, 2)) == 0 + + +def test_SiteIndexConverter_2(): + # test constructor + with pytest.raises(TypeError): + xtal.SiteIndexConverter( + transformation_matrix_to_super=np.array( + [ + [2.0, 0, 0], + [0, 2, 0], + [0, 0, 2], + ] + ), + n_sublattice=2, + ) diff --git a/python/tests/test_structure.py b/python/tests/test_structure.py index 278b8d4..305e1b0 100644 --- a/python/tests/test_structure.py +++ b/python/tests/test_structure.py @@ -1,6 +1,10 @@ +import math + import numpy as np +import pytest import libcasm.xtal as xtal +import libcasm.xtal.structures as xtal_structures def test_make_structure(example_structure_1): @@ -396,3 +400,60 @@ def test_structure_is_equivalent_to(): ) assert structure1.is_equivalent_to(structure2) + + +def test_make_superstructure_1(): + struc = xtal_structures.BCC(r=1) + transformation_matrix = np.array( + [[0.0, 1.0, 1.0], [1.0, 0.0, 1.0], [1.0, 1.0, 0.0]] + ).T + assert transformation_matrix.dtype is np.dtype(np.float64) + with pytest.raises(TypeError): + xtal.make_superstructure(transformation_matrix, struc) + + +def test_make_superstructure_2(): + struc = xtal_structures.BCC(r=1) + transformation_matrix = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]], dtype=int).T + assert transformation_matrix.dtype is np.dtype(np.int64) + xtal.make_superstructure(transformation_matrix, struc) + + +def test_make_superstructure_and_rotate(): + struc = xtal_structures.BCC(r=1) + assert len(struc.atom_type()) == 1 + + rotation_matrix = np.array( + [ + [1 / np.sqrt(2), 1 / np.sqrt(2), 0], + [-1 / np.sqrt(2), 1 / np.sqrt(2), 0], + [0, 0, 1], + ] + ).T + transformation_matrix = np.array( + [ + [0, 1, 1], + [1, 0, 1], + [1, 1, 0], + ], + dtype=int, + ).T + assert math.isclose(np.linalg.det(transformation_matrix), 2.0) + + superstruc = xtal.make_superstructure(transformation_matrix, struc) + L = struc.lattice().column_vector_matrix() + S = superstruc.lattice().column_vector_matrix() + assert np.allclose(S, L @ transformation_matrix) + assert len(superstruc.atom_type()) == 2 + + symop = xtal.SymOp( + matrix=rotation_matrix, + translation=np.zeros((3,)), + time_reversal=False, + ) + rotated_superstruc = symop * superstruc + + L = struc.lattice().column_vector_matrix() + S = rotated_superstruc.lattice().column_vector_matrix() + assert np.allclose(S, rotation_matrix @ L @ transformation_matrix) + assert len(rotated_superstruc.atom_type()) == 2 diff --git a/python/tests/test_unitcellindexconverter.py b/python/tests/test_unitcellindexconverter.py index 0f4d047..0abbf25 100644 --- a/python/tests/test_unitcellindexconverter.py +++ b/python/tests/test_unitcellindexconverter.py @@ -57,3 +57,18 @@ def test_UnitCellIndexConverter_1(): f.never_bring_within() f.always_bring_within() assert f.linear_unitcell_index(np.array([2, 2, 2])) == 0 + + +def test_UnitCellIndexConverter_2(): + # test constructor + with pytest.raises(TypeError): + # test constructor + xtal.UnitCellIndexConverter( + np.array( + [ + [2.0, 0, 0], + [0, 2, 0], + [0, 0, 2], + ] + ) + )