Разделение триклинной ячейки в Python

В настоящее время я анализирую данные молекулярной динамики и хотел бы разделить суперячейку, которую я использую, на части NxNxN. Форма ячейки триклинная, или, другими словами, это параллелепипед, у которого все три основные длины сторон и три главных угла различны. После этого поста здесь я смог понять, как построить изображение моей исходной клетки. Однако я изо всех сил пытаюсь правильно разделить исходную ячейку. На самом деле моя основная проблема заключается в том, что существуют небольшие перемещения подячеек, которые приводят к их смещению друг относительно друга, а также смещению относительно исходной ячейки.

Я почти все сделал правильно с помощью следующего кода:

def subdivide_cell(origin, a, b, c, n):
    subdivisions = []
    for i in range(n):
        for j in range(n):
            for k in range(n):
                sub_origin = origin + np.array([i * a / n, j * b / n, k * c / n])
                sub_a = a / n
                sub_b = b / n
                sub_c = c / n
                subdivisions.append((sub_origin, sub_a, sub_b, sub_c))
    return subdivisions

Я также приложу выходной рисунок, который я получу в нескольких ориентациях, чтобы было ясно, как смещены подячейки. Любое понимание того, как решить остальную часть этой проблемы, приветствуется!

Обновлено: я тестирую код с подразделением 2x2x2, но в идеале мне бы хотелось подразделение 4x4x4. Я ожидаю, что как только 2x2x2 заработает, 4x4x4 тоже будет вполне функциональным.

Ориентация 1Ориентация 2

Здесь вы упускаете некоторую информацию. Вы не можете разделить ячейку, зная только начало координат и (я предполагаю; вы не сказали) три измерения и количество подячеек. Как a,b,c могут определить, правильная это ячейка или перекошенная? (и, конечно, насколько перекошено)? Думаю, вы это знаете, поскольку рисуете перекошенные подячейки. Но вы этого не предоставили

chrslg 10.05.2024 12:01

Я могу предоставить код, который я использовал для исходной триклинной ячейки, если это будет полезно. Однако вы правы, я чувствую, что у меня, вероятно, должно быть такое же угловое состояние, как и для исходной ячейки. Я подозреваю, что мой код, вероятно, обрабатывает подячейки так, как если бы исходная ячейка была ромбоэдрической.

Baba Booey 10.05.2024 17:07

Что вы думаете о моем ответе?

gboffi 13.05.2024 12:04
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
3
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

[Изображение было повернуто вручную, чтобы лучше видеть подразделения]

Ниже приведен код, используемый для создания триклинной ячейки и ее подразделений (этот код должен быть более эффективным, чем код, который вы все еще можете найти в истории редактирования).

Я думаю, что это довольно просто, но если что-то неясно, спрашивайте в комментариях.

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Line3DCollection as lc3d
import numpy as np
from itertools import product

# a solid parallelogram is defined in terms of an origin and 3 vectors,
# when no couple of vectors are orthogonal you have a tricline
o, a, b, c = np.array((
    ( 0.0,  0.0,  0.0),
    ( 6.0,  1.0, -1.0),
    ( 0.0,  7.0,  1.0),
    ( 2.0,  0.0,  7.0),
    ))

# let's get a 3d Axes
ax = plt.figure().add_subplot(projection='3d')

# first the inner cells, then the outer, single one, darker and thicker
draw_n_cells(o, a, b, c, 3, lw=0.5, color='gray')
draw_n_cells(o, a, b, c, 1, lw=1.5, color='k')
plt.show()

def draw_n_cells(o, a, b, c, n, ax=None, lw=1.5, color='blue'):
    ax = ax if ax else plt.gca()
    # the idea is to use two vectors to form a grid of points on one of the
    # six faces of the parallelogram, and draw the lines // to the third
    # vector that arrive to the opposite face, one line per point
    
    # helper vector, equispaced point on the interval [0, 1] spaced 1/n
    d = np.linspace(0, 1, n+1)[:,None] ####> d.shape is (n+1, 1)

    # we make a cycle to have the 2 vectors, r & s, that determine a face and
    # the vector t that determines the line direction and its extension
    for r, s, t in ((a, b, c), (b, c, a), (c, a, b)):
        # arrays containing equispaced 3d points on r and s respectively
        rn, sn = r*d, s*d
        # each point on the grid is defined by two vectors, say v0 and v1, that
        # must be summed to find the position of a point
        # 1. we compute the couples using itertools.product
        v0v1 =  product(rn, sn)
        # 2. we compute the points on the grid, spanning one face, and also the
        # points on the opposite face
        p0_p1 = [[o+p, o+p+t]for p in (v0+v1 for v0, v1 in v0v1)]
        # the list [[p0, p1]] is exactly in the format that's needed for LineCollection3D
        lc = lc3d(p0_p1, lw=lw, color=color)
        # or, more compact
        # lc = lc3d([[o+p, o+p+t]for p in (v0+v1 for v0, v1 in product(r*d, s*d))])
        # the line collection must be placed in the 3D Axes
        ax.add_artist(lc)
        ax.autoscale()            

В этом случае все было бы в порядке, если бы у вас уже были векторы ребер, верно?

Baba Booey 15.05.2024 02:01

@BabaBooey Вы определяете триклинную ячейку через начало координат O и 3 вектора V1, V2 и V3 или через 4 точки P0, P1, P2, P3. В первом случае у вас уже есть векторы ребер, во втором 3 вектора можно вычислить как V1=P1-P0 и т. д.

gboffi 15.05.2024 14:41

Ах хорошо. Мне нужно будет вычислить края вектора, чтобы это можно было правильно использовать, но это не должно быть слишком сложно. Теперь, когда я не занят, я протестирую это и посмотрю, как это работает. Я отчитаюсь в ближайшее время

Baba Booey 15.05.2024 18:49

Кажется, это работает очень хорошо, спасибо!

Baba Booey 15.05.2024 21:12

Другие вопросы по теме