From 130826b9cd37743ce950afec2abda264e67badcf Mon Sep 17 00:00:00 2001 From: jeremiah Date: Wed, 17 Jul 2024 12:12:45 -0700 Subject: [PATCH 1/2] expose lattice strain cost methods --- python/libcasm/mapping/info/__init__.py | 2 ++ python/src/mapping_info.cpp | 37 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/python/libcasm/mapping/info/__init__.py b/python/libcasm/mapping/info/__init__.py index 43a8409..2817fec 100644 --- a/python/libcasm/mapping/info/__init__.py +++ b/python/libcasm/mapping/info/__init__.py @@ -12,4 +12,6 @@ StructureMappingResults, has_same_prim, pretty_json, + lattice_isotropic_strain_cost, + lattice_symmetry_breaking_strain_cost, ) diff --git a/python/src/mapping_info.cpp b/python/src/mapping_info.cpp index 5820ac2..a44790d 100644 --- a/python/src/mapping_info.cpp +++ b/python/src/mapping_info.cpp @@ -10,6 +10,7 @@ #include "casm/mapping/AtomMapping.hh" #include "casm/mapping/LatticeMapping.hh" #include "casm/mapping/StructureMapping.hh" +#include "casm/mapping/lattice_cost.hh" #include "casm/mapping/io/json_io.hh" #include "pybind11_json/pybind11_json.hpp" @@ -770,6 +771,42 @@ PYBIND11_MODULE(_mapping_info, m) { }, "Pretty-print JSON to string.", py::arg("data")); + m.def( + "lattice_isotropic_strain_cost", &isotropic_strain_cost, + R"pbdoc( + Return the isotropic strain cost for a lattice deformation. + + Parameters + ---------- + deformation_gradient : array_like, shape=(3,3) + The parent-to-child deformation gradient tensor, :math:`F`, a shape=(3,3) + matrix. + + Returns + ------- + float : The isotropic strain cost for the lattice deformation given by :math:`F`. + )pbdoc", + py::arg("deformation_gradient")); + + m.def( + "lattice_symmetry_breaking_strain_cost", &symmetry_breaking_strain_cost, + R"pbdoc( + Return the symmetry-breaking strain cost for a lattice deformation. + + Parameters + ---------- + deformation_gradient : array_like, shape=(3,3) + The parent-to-child deformation gradient tensor, :math:`F`, a shape=(3,3) + matrix. + lattice1_point_group : list[:class:`xtal::SymOp`] + The point group of the parent crystal lattice. + + Returns + ------- + float : The symmetry-breaking strain cost for the lattice deformation given by :math:`F`. + )pbdoc", + py::arg("deformation_gradient"), py::arg("lattice1_point_group")); + #ifdef VERSION_INFO m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO); #else From 5f20cb00f9eb2e278c939744483a12b3b2658038 Mon Sep 17 00:00:00 2001 From: jeremiah Date: Wed, 17 Jul 2024 13:38:55 -0700 Subject: [PATCH 2/2] lattice mapping without reorientation --- python/libcasm/mapping/methods/__init__.py | 4 ++ python/libcasm/mapping/methods/_methods.py | 59 ++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 python/libcasm/mapping/methods/_methods.py diff --git a/python/libcasm/mapping/methods/__init__.py b/python/libcasm/mapping/methods/__init__.py index d0c78b9..59c7d17 100644 --- a/python/libcasm/mapping/methods/__init__.py +++ b/python/libcasm/mapping/methods/__init__.py @@ -1,4 +1,8 @@ """Easy-to-use mapping methods""" +from ._methods import ( + map_lattices_without_reorientation, +) + from ._mapping_methods import ( make_mapped_lattice, make_mapped_structure, diff --git a/python/libcasm/mapping/methods/_methods.py b/python/libcasm/mapping/methods/_methods.py new file mode 100644 index 0000000..35b130a --- /dev/null +++ b/python/libcasm/mapping/methods/_methods.py @@ -0,0 +1,59 @@ +import typing + +import libcasm.mapping.info as mapinfo +import libcasm.xtal as xtal +import numpy as np + + +def map_lattices_without_reorientation( + lattice1: xtal.Lattice, + lattice2: xtal.Lattice, + transformation_matrix_to_super: typing.Optional[np.ndarray] = None, +) -> mapinfo.LatticeMapping: + """Map lattices without reorienting the child. + + This function may be used to find the lattice mapping from + an ideal structure to a deformed structure during geometric + relaxation via DFT. The lattice mapping has the form + + .. math:: + + FL_1T = L_2 + + where :math:`F` is the deformation tensor, :math:`L_1` is + the ideal parent lattice, :math:`L_2` is the deformed child + lattice, and :math:`T` is an optional transformation matrix + from the parent to the child which may be provided if :math:`L2` + is a superlattice of :math:`L1`. + + Parameters + ---------- + lattice1: xtal.Lattice + The parent crystal lattice. + lattice2: xtal.Lattice + The child crystal lattice. + transformation_matrix_to_super: Optional[np.ndarray] = None + An integer shape=(3,3) transformation matrix that generates a superlattice of `lattice1`. + The transformation matrix that generates a superlattice of `lattice1`. + If None, :math:`T` is set to the identity matrix. + + Returns + ------- + lattice_mapping: mapinfo.LatticeMapping + The lattice mapping from the parent to the child. + """ + if transformation_matrix_to_super is None: + transformation_matrix_to_super = np.eye(3, dtype=int) + + # calculate deformation gradient + l1 = lattice1.column_vector_matrix() + l2 = lattice2.column_vector_matrix() + deformation_gradient = ( + l2 @ np.linalg.inv(transformation_matrix_to_super) @ np.linalg.inv(l1) + ) + lattice_mapping = mapinfo.LatticeMapping( + deformation_gradient=deformation_gradient, + transformation_matrix_to_super=transformation_matrix_to_super, + reorientation=np.eye(3, dtype=float), + ) + return lattice_mapping