Оборачивание заданных координат (x, y, z) в скрученную структуру - PullRequest
0 голосов
/ 28 августа 2018

Я пытаюсь обернуть (x, y, z) координаты на полосу Мёбиуса (топологическую структуру, полученную путем скручивания один раз и соединения концов полосы).

Структура (для которой я могу создать координаты xyz) выглядит следующим образом (из RG ) с использованием следующего кода.

import numpy as np
import matplotlib.pyplot as plt

bLength=1.6
numPoints=10
radius = bLength*numPoints / (2 * np.pi)
theta = np.linspace(0,2*np.pi,numPoints,endpoint=False)
dtheta=theta[1]-theta[0]
x0,y0=(radius * np.cos(theta)), (radius * np.sin(theta))
x1,y1=(radius * np.cos(theta+dtheta/2)) , (radius * 
np.sin(theta+dtheta/2))
#plt.plot(x0,y0)
#plt.show()
#plt.plot(x1,y1)
#plt.show()
cons0=np.ones(x0.shape)*0
cons1=np.ones(x1.shape)*2
np.savetxt('cooRing1.csv',np.c_[x0,y0,cons0],delimiter=' ')
np.savetxt('cooRing2.csv',np.c_[x1,y1,cons1],delimiter=' ')
cat cooRing1.csv cooRing2.csv > coordinates.csv

[! [Введите описание изображения здесь] [3]] [3]

Я хочу отобразить координаты XYZ на полосе Мёбиуса.

Следующий пример приведен на веб-сайте для другой полосы (также в коде используется модуль, который не является общедоступным)

import Twister as Twister    
import math

def displacement(x, width, wrapping_angle):
    """
       Function for converting a nanosheet coordinate into a partly wrapped nanotube
       @param x : Coordinates of nanosheet atom
       @param width : Width of the nano-sheet
       @param wrapping_angle : maximum wrapping angle of the nanotube in radians
    """
    # calculate the average radius of the incomplete wrapped tube
    radius = width/wrapping_angle
    # find the angle of the current atom
    angle = (x[2]-width/2.)/radius
    # calculate the radius of the current atom
    atom_radius = radius+x[1]

    # return atom position of the wrapped atom
    return numpy.array([x[0], atom_radius*math.cos(angle),atom_radius*math.sin(angle)])

def configuration(n, m, repetition):
    """
       Function for generating a moebius molecule
       @param n : Chiral vector index
       @param m : Chiral vector index
       @param repetition : Repetition along z
    """

    # build n,m ribbon
    ribbon = NanoRibbon(n,m)
    ribbon = ribbon.repeat(1,1,repetition)

    # get properties of the ribbon
    lattice = ribbon.bravaisLattice()
    elements = ribbon.elements()
    cartesian_coordinates=ribbon.cartesianCoordinates().inUnitsOf(Angstrom)

    # calculate the length of the 1-d structure
    z_length = numpy.linalg.norm(lattice.primitiveVectors()[2].inUnitsOf(Angstrom)) 

    # calculate twist parameters
    rotation_angle_per_z =  math.pi /z_length
    rotation_axis = numpy.array([0,0,1])
    rotation_axis_center = numpy.sum(cartesian_coordinates,axis=0)/len(cartesian_coordinates)

    # define a function of one variable, f(c),  for displacing the atoms
    f = lambda c : Twister.displacement(c, rotation_angle_per_z, rotation_axis, 
                                rotation_axis_center, 0.,z_length)
    # apply the function to find new displaced coordinates
    cartesian_coordinates = numpy.apply_along_axis(f, 1, cartesian_coordinates)
    cartesian_center = numpy.sum(cartesian_coordinates,axis=0)/len(cartesian_coordinates)
    cartesian_coordinates = cartesian_coordinates - cartesian_center


    # define a function of one variable, f(c),  for displacing the atoms
    f = lambda c : displacement(c, z_length,2.0*math.pi) 
    # apply the function to find new displaced coordinates
    cartesian_coordinates = numpy.apply_along_axis(f, 1, cartesian_coordinates)

    return MoleculeConfiguration(
            elements=elements,
            cartesian_coordinates=cartesian_coordinates * Angstrom
            )

# Instantiate the builder object and choose our title
builder = Builder()
builder.title('Moebius ribbon')

# Set the configuration generator
builder.setConfigurationGenerator(configuration)

# Tube properties group
builder.newGroup('Tube parameters')
builder.integer( 'n', 6, 'n', min=1, max=1000)
builder.integer( 'm', 0, 'm', min=0, max=1000)
builder.integer( 'repetition', 40, 'C-direction', min=1, max=1000)

Есть ли в Python аналогичный модуль, чтобы я мог построить желаемую структуру, а также создать координаты XYZ? Или как я могу продолжить, чтобы завершить код?

1 Ответ

0 голосов
/ 06 сентября 2018

Невозможно преобразовать координаты одного из ваших колец 2xN в полосу Мёбиуса. Это потому, что чередующаяся полоса с половиной скручивания должна иметь нечетное число атомов, в то время как ваши текущие кольца всегда имеют четное число. Вам нужно будет вырезать один атом или добавить один, чтобы твист работал. Может быть, вы могли бы сделать преобразование, которое могло бы работать, помещая первый и последний атомы друг на друга, но я думаю, что это было бы очень некрасиво (и математически, и, возможно, также в графике).

Хотя это, вероятно, делает непрактичным то, что вы просите с помощью 3D-преобразования, вы можете вместо этого создать координаты с нуля с желаемым поворотом. Просто создайте единый массив точек для одного края полосы (наличие только одного края - одна из вещей, которые делают полосу Мёбиуса странной). Край образует две петли вокруг круга, по одному на каждой стороне полосы, и поворот происходит с половиной скорости основного вращения.

Вот мой удар:

bLength=1.6
n = 10
numPoints = 2*n + 1
radius = bLength*numPoints / (4*np.pi)   # 4*pi because the edge goes around the circle twice
theta = np.linspace(0, 4*np.pi, numPoints, endpoint=False)   # here too
x = (radius + np.cos(theta/2)) * np.cos(theta)
y = (radius + np.cos(theta/2)) * np.sin(theta)
z = np.sin(theta/2)

plt.plot(x, y) # I don't know how to graph in 3d, so only x and y here
plt.show()

output of the plot

Это делает полосу шириной 2, как ваш текущий код. Если это неправильная ширина, вы должны умножить cos слагаемые, добавленные к радиусу при расчете x и y, и значение sin, используемое для z, на половину желаемой ширины.

Обратите внимание, что в то время как этот код может производить то, что вы хотите, координаты, вероятно, бессмысленны, когда речь идет о физическом описании реального кольца атомов. Некоторые расстояния между координатами будут сильно отличаться от других (например, внутри полосы по сравнению с внешней стороной, когда она почти плоская), и настоящая полоса Мёбиуса, состоящая из атомов (если такая вещь вообще может быть сделана), будет вероятно, сложить каким-то образом, а не скручивать с одинаковой скоростью (полоса Мебиуса, сделанная из бумаги, тоже не скручивается). Найти точное расположение реальных атомов было бы намного более сложной проблемой (и проблемой для физика, а не программиста).

...