대칭 고유 원자 좌표

Sep 18 2020

내가 Mathematica에 대해 좋아하는 한 가지는 분자의 이름에서 원자의 추정 좌표로 쉽게 이동할 수 있다는 것입니다.

AtomList[Molecule[Entity["Chemical", "Toluene"]], All, {"AtomicNumber", "AtomCoordinates"}]

(이상하게도 "AtomCoordinates"는 "AtomList"문서에 나타나지 않습니다.)

포인트 그룹도 쉽게 얻을 수 있습니다.

Molecule[Entity["Chemical", "Toluene"]]["PointGroup"]

이것은 GAMESS를 실행하고 양자 화학 계산을 수행하는 데 필요한 입력이기 때문에 흥미 롭습니다 (물론 JM이 이러한 좌표가 휴리스틱 추측이라고 알려 주었으므로 기하학 최적화로 시작 ).

그러나, 정말,이 아닙니다 정확히 내가 정말 필요한 경우에만 대칭 고유 원자의 좌표는 : 내가 필요로하는 입력.

GAMESS 입력에 사용할 수있는 대칭 고유 원자의 좌표를 얻는 방법이 없다고 생각합니까? 포인트 그룹 대칭과 관련된 몇 가지 기능 이 있다는 것을 알고 있지만 어떻게할지 생각하지 못했습니다.

명확히하기 위해 PointGroup 속성이 제공하는 포인트 그룹과 일치하는 답변을 찾고 있습니다. 예를 들어, 위의 코드는 의자 형태에 해당하는 사이클로 헥산에 대한 D3d의 점 그룹을 제공합니다. 따라서 축과 적도는 D3d의 대칭 요소에 의해 서로 변환 될 수 없기 때문에 탄소, 적도 수소 및 축 수소의 세 가지 등가 등급이 있어야합니다.

답변

2 JasonB. Sep 28 2020 at 12:13

이를 해결하기위한 일반적인 계획은

  1. 주어진 분자에 대한 모든 대칭 변환을 생성합니다.
  2. 이러한 변환을 각 원자 좌표에 적용하여 각 원자에 대한 좌표 목록을 제공합니다.
  3. 동등한 좌표 목록을 제공하는 그룹 원자는 동등한 것으로 간주됩니다.

슬프게도 Wolfram 개발자는 내장 함수를 통해 주어진 대칭 요소와 관련된 실제 변환 함수를 제공하지 않습니다. 그러나 그들은 "SymmetryElements"재산 에 대한 충분한 정보를 제공하여 직접 구성합니다.

In[26]:= Molecule["methane"]["SymmetryElements"] // pf2

Out[26]= {
    <|
        "Operation" -> "Rotation", "Name" -> Subscript["C", "3"],
        "Degree" -> 3, "UniqueOperationsCount" -> 2, 
  "RotationAxis" -> InfiniteLine[
                {0., 0., 0.},
                {0.9312106494091753, 0.3062515387515941, 0.19762773448891885}
            ]
    |>,
    ........,
    <|
        "Operation" -> "Reflection", "Name" -> "\[Sigma]", 
  "Degree" -> 1, "UniqueOperationsCount" -> 1,
        "SymmetryPlane" -> Hyperplane[
                {-0.6671653488434035, -0.16935533665066543, -0.7254027620919287},
                {0., 0., 0.}
            ]
    |>
 }

해당 출력의 구조를 조사하여 대칭 요소에서 변환을 반환하는 함수를 작성할 수 있습니다. KeyValuePattern쉽게 읽을 수있는 defitions 에 사용 하고 싶습니다 .

symmetryOperation[KeyValuePattern[{"Operation"->"Rotation","Degree"->d_,"RotationAxis"->InfiniteLine[point_,direction_]}]] := RotationTransform[(2 * Pi) / d, direction, point];
symmetryOperation[KeyValuePattern[{"Operation"->"ImproperRotation","Degree"->d_,"RotationAxis"->InfiniteLine[point_,direction_]}]] := ReflectionTransform[direction, point] @* RotationTransform[(2 * Pi) / d, direction, point];
reflectpoint[point_, center_] := point + 2 * (center + -point);
symmetryOperation[KeyValuePattern[{"Operation"->"Inversion","InversionCenter"->Point[center_]}]] := Composition[
    ReflectionTransform[{1, 0, 0}, center], 
    ReflectionTransform[{0, 1, 0}, center], 
    ReflectionTransform[{0, 0, 1}, center]
];
symmetryOperation[KeyValuePattern[{"Operation"->"Reflection","SymmetryPlane"->Hyperplane[normal_,point_]}]] := ReflectionTransform[normal, point]

이제 분자에 대한 모든 대칭 변환을 반환하는 함수를 작성하여 Identity 요소를 포함하지 않음으로써 Wolfram이 만든 감독을 수정합니다.

symmetryTransforms[mol_] := Join[{Identity}, Map[symmetryOperation, mol @ "SymmetryElements"]];

이제 각 변환을 각 원자 좌표에 적용하는 함수로 모두 감싸고 동일한 좌표 목록을 생성하는 변환을 수집합니다.

symmetryUniqueAtomIndices[mol_, tolerance_:0.1] := Module[
    {
        transforms = symmetryTransforms @ mol,
        points = QuantityMagnitude @ mol @ "AtomCoordinates"
    },
    PrependTo[transforms, Identity];
    GatherBy[Range @ Length @ points,
        Sort[
            DeleteDuplicates[Round[Through[transforms[Part[points, #]]], tolerance]]
        ]&
    ]
]

이것은 GatherBy동등한 원자를 그룹화하는 데 사용 됩니다. 여기서 중요한 부분은 변환 된 좌표를 정규화하는 함수를 만드는 것입니다.이를 위해 숫자 값을 반올림하고 중복을 삭제 한 다음 정렬합니다. 이 단계에서 개선의 여지가있을 것입니다.

이 예 에서 다른 시클로 헥산 형태를 볼 수 있습니다 .

labels = {"planar", "chair", "twist-boat", "boat", "half-boat", "half-chair"};
conformers = AssociationThread[
    labels -> CloudImport[
        CloudObject["https://www.wolframcloud.com/objects/555b1b48-9f89-45ef-a9e2-49c8fe5228b6"],
        "SDF"
    ]
];

다른 형태의 대칭을 비교하십시오.

In[10]:= symmetryUniqueAtomIndices /@ conformers

Out[10]= <|"planar" -> {{1, 2, 3, 4, 5, 6}, {7, 8, 9, 10, 11, 12, 13, 
    14, 15, 16, 17, 18}}, 
 "chair" -> {{1, 2, 3, 4, 5, 6}, {7, 9, 12, 13, 16, 18}, {8, 10, 11, 
    14, 15, 17}}, 
 "twist-boat" -> {{1, 4}, {2, 3, 5, 6}, {7, 8, 13, 14}, {9, 12, 15, 
    17}, {10, 11, 16, 18}}, 
 "boat" -> {{1, 4}, {2, 3, 5, 6}, {7, 14}, {8, 13}, {9, 11, 15, 
    18}, {10, 12, 16, 17}}, 
 "half-boat" -> {{1}, {2, 6}, {3, 5}, {4}, {7}, {8}, {9, 18}, {10, 
    17}, {11, 15}, {12, 16}, {13}, {14}}, 
 "half-chair" -> {{1, 4}, {2, 3}, {5, 6}, {7, 13}, {8, 14}, {9, 
    12}, {10, 11}, {15, 17}, {16, 18}}|>

각 등가 그룹에서 하나의 원자 만 원하면 다음과 같이 사용하십시오.

In[11]:= Map[First] /@ %

Out[11]= <|"planar" -> {1, 7}, "chair" -> {1, 7, 8}, 
 "twist-boat" -> {1, 2, 7, 9, 10}, "boat" -> {1, 2, 7, 8, 9, 10}, 
 "half-boat" -> {1, 2, 3, 4, 7, 8, 9, 10, 11, 12, 13, 14}, 
 "half-chair" -> {1, 2, 5, 7, 8, 9, 10, 15, 16}|>

다음과 같은 방법으로 대칭 그룹을 시각화 할 수 있습니다.

MoleculePlot3D[conformers["chair"], 
 symmetryUniqueAtomIndices@conformers["chair"]]

이 이미지에서 주어진 색상의 모든 원자는 사용 가능한 대칭 작업에서 동일합니다. 이제 수소 원자가 보라색의 적도 (고리에서 '발사')와 파란색의 축 (주 대칭 축에 평행 한 결합 포함)의 두 가지 범주로 분류되는 것을 볼 수 있습니다.

4 bobthechemist Sep 19 2020 at 01:58

Jason B는 내가 전에 이것을 보았지만 다음은 GAMES 입력 예제 중 일부를 합리적으로 잘 재현한다고 생각합니다.

f[mol_] := Module[{al, out},
  al = AtomList[Molecule[mol], 
    All, {"AtomicNumber", "AtomCoordinates"}];
  out = QuantityMagnitude /@ 
    Flatten /@ al[[First /@ Molecule[mol]["SymmetryEquivalentAtoms"]]];
  out /. z_Integer :> Sequence[ElementData[z, "Abbreviation"], z]
  ]

f["Toluene"]