{-| 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