Source code for magnopy._local_rf

# ================================== LICENSE ===================================
# Magnopy - Python package for magnons.
#
# Copyright (C) 2023 Magnopy Team
#
# e-mail: anry@uv.es, web: magnopy.org
#
# This program is free software: you  can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the  Free Software
# Foundation,  either  version 3  of the License,  or (at your option) any later
# version.
#
# This program is distributed in the  hope  that it will be useful,  but WITHOUT
# ANY WARRANTY;  without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the  GNU General Public License  along with
# this program.  If not, see <https://www.gnu.org/licenses/>.
# ================================ END LICENSE =================================


import numpy as np

# Save local scope at this moment
old_dir = set(dir())
old_dir.add("old_dir")


[docs] def span_local_rf(direction_vector, hybridize=False, _normalize=True): r""" Spans local right-handed reference frame from the direction vector. Parameters ---------- direction_vector : (3, ) |array-like|_ Direction of the z axis of the local reference frame. hybridize : bool, default False * If ``hybridize == True``, then returns ``p_alpha, z_alpha``. * If ``hybridize == False``, then returns ``x_alpha, y_alpha, z_alpha``. Returns ------- x_alpha : (3, ) :numpy:`ndarray` y_alpha : (3, ) :numpy:`ndarray` p_alpha : (3, ) :numpy:`ndarray` ``p_alpha = x_alpha + 1j * y_alpha``. z_alpha : (3, ) :numpy:`ndarray` See Also -------- span_local_rfs Examples -------- Two special cases are handled as .. doctest:: >>> import magnopy >>> x, y, z = magnopy.span_local_rf([0, 0, 1]) >>> x array([1., 0., 0.]) >>> y array([0., 1., 0.]) >>> z array([0., 0., 1.]) >>> p, z = magnopy.span_local_rf([0, 0, 1], hybridize=True) >>> p array([1.+0.j, 0.+1.j, 0.+0.j]) >>> z array([0., 0., 1.]) .. doctest:: >>> import magnopy >>> x, y, z = magnopy.span_local_rf([0, 0, -1]) >>> x array([ 0., -1., 0.]) >>> y array([-1., 0., 0.]) >>> z array([ 0., 0., -1.]) >>> p, z = magnopy.span_local_rf([0, 0, -1], hybridize=True) >>> p array([ 0.-1.j, -1.+0.j, 0.+0.j]) >>> z array([ 0., 0., -1.]) For the arbitrary direction the global reference frame is rotated as a whole .. doctest:: >>> import magnopy >>> x, y, z = magnopy.span_local_rf([1, 1, 1]) >>> x array([ 0.78867513, -0.21132487, -0.57735027]) >>> y array([-0.21132487, 0.78867513, -0.57735027]) >>> z array([0.57735027, 0.57735027, 0.57735027]) >>> p, z = magnopy.span_local_rf([1, 1, 1], hybridize=True) >>> p array([ 0.78867513-0.21132487j, -0.21132487+0.78867513j, -0.57735027-0.57735027j]) >>> z array([0.57735027, 0.57735027, 0.57735027]) """ dv = np.array(direction_vector, dtype=float) if np.allclose(dv, np.zeros(3)): raise ValueError("Zero vector.") scale = np.linalg.norm(dv) dv /= scale if np.allclose(dv, [0, 0, 1]): x_alpha = np.array([1, 0, 0], dtype=float) y_alpha = np.array([0, 1, 0], dtype=float) elif np.allclose(dv, [0, 0, -1]): x_alpha = np.array([0, -1, 0], dtype=float) y_alpha = np.array([-1, 0, 0], dtype=float) else: z_dir = [0, 0, 1] sin_rot_angle = np.linalg.norm(np.cross(z_dir, dv)) cos_rot_angle = np.dot(z_dir, dv) # direction_vector and z_dir are unit vectors ux, uy, uz = np.cross(z_dir, dv) / sin_rot_angle x_alpha = np.array( [ ux**2 * (1 - cos_rot_angle) + cos_rot_angle, ux * uy * (1 - cos_rot_angle) + uz * sin_rot_angle, ux * uz * (1 - cos_rot_angle) - uy * sin_rot_angle, ] ) y_alpha = np.array( [ ux * uy * (1 - cos_rot_angle) - uz * sin_rot_angle, uy**2 * (1 - cos_rot_angle) + cos_rot_angle, uy * uz * (1 - cos_rot_angle) + ux * sin_rot_angle, ] ) if not _normalize: x_alpha *= scale y_alpha *= scale dv *= scale if hybridize: return x_alpha + 1j * y_alpha, dv return x_alpha, y_alpha, dv
[docs] def span_local_rfs(directional_vectors, hybridize=False, _normalize=True): r""" Spans a set of local right-handed reference frames from a set of the direction vectors. Parameters ---------- direction_vectors : (M, 3) |array-like|_ Direction of the z axis of the local reference frames. hybridize : bool, default False * If ``hybridize == True``, then returns ``p_alphas, z_alphas``. * If ``hybridize == False``, then returns ``x_alphas, y_alphas, z_alphas``. Returns ------- x_alphas : (M, 3) :numpy:`ndarray` y_alphas : (M, 3) :numpy:`ndarray` p_alphas : (M, 3) :numpy:`ndarray` ``p_alpha = x_alpha + 1j * y_alpha``. z_alphas : (M, 3) :numpy:`ndarray` See Also -------- span_local_rf Examples -------- .. doctest:: >>> import magnopy >>> x, y, z = magnopy.span_local_rfs([[0, 0, 1], [0, 0, -1], [1, 1, 1]]) >>> x array([[ 1. , 0. , 0. ], [ 0. , -1. , 0. ], [ 0.78867513, -0.21132487, -0.57735027]]) >>> y array([[ 0. , 1. , 0. ], [-1. , 0. , 0. ], [-0.21132487, 0.78867513, -0.57735027]]) >>> z array([[ 0. , 0. , 1. ], [ 0. , 0. , -1. ], [ 0.57735027, 0.57735027, 0.57735027]]) """ results = [] for directional_vector in directional_vectors: results.append( span_local_rf( direction_vector=directional_vector, hybridize=hybridize, _normalize=_normalize, ) ) results = np.array(results) if hybridize: return results[:, 0], results[:, 1] return results[:, 0], results[:, 1], results[:, 2]
# Populate __all__ with objects defined in this file __all__ = list(set(dir()) - old_dir) # Remove all semi-private objects __all__ = [i for i in __all__ if not i.startswith("_")] del old_dir