将给定坐标(x,y,z)包裹在扭曲的结构中

时间:2018-08-28 14:36:54

标签: python python-3.x csv numpy mobius

我正在尝试将{x,y,z)坐标包装在Mobius strip(通过扭曲一次并连接条带末端而获得的拓扑结构)上。

使用以下代码(从RG开始),其结构(我可以为其创建xyz坐标)。

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]

我想在Mobius带上的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 :(得分:0)

无法将您的2xN环之一的坐标转换为莫比乌斯带。那是因为其中带半个扭曲的交替带必须具有奇数个原子,而您的当前环始终具有偶数。您需要切掉一个原子或添加一个原子,以使扭曲起作用。 也许您可以通过将第一个原子和最后一个原子堆叠在一起来进行转换,但是我认为这非常丑陋(无论是数学上还是图形上)。

尽管可能无法通过3D转换满足您的要求,但您可以改为从头开始创建具有所需扭曲的坐标。只需为条带的单个边缘生成单个点阵列(只有一条边缘是使Möbius条带怪异的原因之一)。边缘在圆上绕了两个圈,在钢带的每一侧上一个圈,并且扭曲发生的速度是主旋转速度的一半。

这是我的目标:

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,就像您当前的代码一样。如果宽度不是正确的宽度,则应在计算cosx时将添加到半径的y项与用于{{1}的sin值相乘}缩小一半。

请注意,尽管这段代码可能会产生您想要的结果,但在物理上描述原子的实际环时,坐标可能毫无意义。坐标之间的某些距离将与其他距离大不相同(例如,在条带的内部而当条带几乎平坦时,则在外部),而真正的由原子构成的莫比乌斯条带(如果可以做到的话)可能会以某种方式折叠,而不是以均匀的速度扭曲(纸制成的莫比乌斯带也不会以这种方式扭曲)。确切地找到真实原子的排列方式将是一个更困难的问题(也是物理学家而不是程序员的问题)。