symmetry-operations-symbols-0.0.2.0: src/Data/Matrix/SymmetryOperationsSymbols/Calc.hs
{-|
Module : Data.Matrix.SymmetryOperationsSymbols.Calc
Description : Translate SymopGeom to matrix
Copyright : (c) Jun Narumi, 2018-2020
License : MIT
Maintainer : narumij@gmail.com
Stability : experimental
-}
module Data.Matrix.SymmetryOperationsSymbols.Calc (
deriveSymmetryOperation
, correpondToRotInversion
, correpondToNFoldRotation
, correpondToGlideOrReflection
) where
import Data.Ratio
import Data.Matrix
import Data.Fixed
import Data.Maybe
import Data.Matrix.SymmetryOperationsSymbols.Common
import Data.Matrix.SymmetryOperationsSymbols.Symbol
-- (<|>)の衝突を避けたくてParse.hsと分けてある
deriveSymmetryOperation :: (Monad m, Integral a)
=> (SymbolSenseVectorOrientation -> m String)
-> SymbolSenseVectorOrientation
-> m (Matrix (Ratio a))
deriveSymmetryOperation lookupFunc elements = calcMatrix elements <$> lookupFunc elements
calcMatrix :: Integral a => SymbolSenseVectorOrientation -> String -> Matrix (Ratio a)
calcMatrix (symbol,sense,vector,orientation) = calc vector' orientation
where
vector' = fromMaybe vector . fromSymbol $ symbol
fromSymbol A = Just "1/2,0,0"
fromSymbol B = Just "0,1/2,0"
fromSymbol C = Just "0,0,1/2"
fromSymbol _ = Nothing
-- 対称操作の幾何表現から行列表現へ変換する際の計算部分
calc :: Integral a => String -> String -> String -> Matrix (Ratio a)
calc vector orientation transCoord
-- matrixWの回転操作部分と生成したwを連結します
= totalPart matrixW vector' orientation'
where
-- 文字列から各種行列(ベクター)を生成します
matrixW = fromXYZ'' transCoord
vector' = fromVec vector
orientation' = fromVec orientation
-- ベクトル表記から3x1行列を生成する
fromVec = transPart . fromXYZ''
totalPart :: Integral a => Matrix (Ratio a) -> Matrix (Ratio a) -> Matrix (Ratio a) -> Matrix (Ratio a)
totalPart matrixW vector orientation
-- matrixWの回転操作部分と生成したwを連結します
= rotPart matrixW <|> transPart' matrixW vector orientation
transPart' :: Integral a => Matrix (Ratio a) -> Matrix (Ratio a) -> Matrix (Ratio a) -> Matrix (Ratio a)
transPart' matrixW vector orientation
= elementwiseMod1 w
where
-- 0 <= x < 1 となるように全要素の剰余をとる
elementwiseMod1 m = flip mod' 1 <$> m
-- wl = (I-W)x の計算をします
wl = multStd matrixIW orientation
wg = vector
-- w = wl + wgの計算をします
-- inversionの場合、参照論文に記載がないが、別の計算が必要となり、w関数の最初の行
-- 試行錯誤でみつけたもので根拠となる論文をまだみつけていないが、
-- (ii) (a)の逆算でこうなった
w | isRotInversion matrixW = multStd matrixIW vector
| otherwise = elementwise (+) wl wg
-- 行列 I-W
matrixIW = iw matrixW
isRotInversion :: Integral a => Matrix (Ratio a) -> Bool
isRotInversion matrix
= correpondToRotInversion tr det
where
tr = trace (rotPart matrix)
det = detLU (rotPart matrix)
type Trace a = Ratio a
type Determinant a = Ratio a
-- Table 11.2.1.1. Identification of the type of the rotation part of the symmetry operation
correpondToRotInversion :: Integral a => Trace a -> Determinant a -> Bool
correpondToRotInversion (-3) (-1) = True -- -1
correpondToRotInversion (-2) (-1) = True -- -6
correpondToRotInversion (-1) (-1) = True -- -4
correpondToRotInversion 0 (-1) = True -- -3
correpondToRotInversion _ _ = False
correpondToNFoldRotation :: Integral a => Trace a -> Determinant a -> Bool
correpondToNFoldRotation (-1) 1 = True -- 2
correpondToNFoldRotation 0 1 = True -- 3
correpondToNFoldRotation 1 1 = True -- 4
correpondToNFoldRotation 2 1 = True -- 6
correpondToNFoldRotation _ _ = False
correpondToGlideOrReflection :: Integral a => Trace a -> Determinant a -> Bool
correpondToGlideOrReflection 1 (-1) = True -- m
correpondToGlideOrReflection _ _ = False