Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用python中的pivot算法实现三维晶格中的自回避随机行走_Python_Computational Geometry - Fatal编程技术网

使用python中的pivot算法实现三维晶格中的自回避随机行走

使用python中的pivot算法实现三维晶格中的自回避随机行走,python,computational-geometry,Python,Computational Geometry,过去几天我一直在研究一个问题,它涉及到使用pivot算法创建一个自避免随机游动,然后实现另一个代码,在3d晶格中放置球形内含物。我写了两个代码,一个代码使用自避免随机游走算法生成球体坐标,另一个代码使用第一个程序生成的坐标,然后在abaqus中创建一个包含球形内含物的3d晶格 运行代码后将生成的结果: 现在是放大部分(以红色边界标记) 问题:生成的球体正在相互合并,如何避免这种情况,我没有想法了。我只需要一些方向或算法来处理 我写的代码如下: 代码1:生成球体的坐标 # Functions

过去几天我一直在研究一个问题,它涉及到使用pivot算法创建一个自避免随机游动,然后实现另一个代码,在3d晶格中放置球形内含物。我写了两个代码,一个代码使用自避免随机游走算法生成球体坐标,另一个代码使用第一个程序生成的坐标,然后在abaqus中创建一个包含球形内含物的3d晶格

运行代码后将生成的结果:

现在是放大部分(以红色边界标记)

问题:生成的球体正在相互合并,如何避免这种情况,我没有想法了。我只需要一些方向或算法来处理

我写的代码如下: 代码1:生成球体的坐标

# Functions of the code: 1) This code generates the coordinates for the spherical fillers using self avoiding random walk which was implemented by pivot algorithm
# Algorithm of the code: 1)Prepare an initial configuration of a N steps walk on lattice(equivalent N monomer chain)
#                        2)Randomly pick a site along the chain as pivot site
#                        3)Randomly pick a side(right to the pivot site or left to it), the chain on this side is used for the next step.
#                        4)Randomly apply a rotate operation on the part of the chain we choose at the above step.
#                        5)After the rotation, check the overlap between the rotated part of the chain and the rest part of the chain. 
#                        6)Accept the new configuration if there is no overlap and restart from 2th step. 
#                        7)Reject the configuration and repeat from 2th step if there are overlaps.
################################################################################################################################################################
# Modules to be imported are below
import numpy as np
import timeit
from scipy.spatial.distance import cdist
import math
import random
import sys
import ast

# define a dot product function used for the rotate operation
def v_dot(a):return lambda b: np.dot(a,b)

def distance(x, y): #The Euclidean Distance to Spread the spheres initiallly
    if len(x) != len(y):
        raise ValueError, "vectors must be same length"
    sum = 0
    for i in range(len(x)):
        sum += (x[i]-y[i])**2
    return math.sqrt(sum)

x=1/math.sqrt(2)
class lattice_SAW: # This is the class which creates the self avoiding random walk coordinates
    def __init__(self,N,l0):
        self.N = N #No of spheres
        self.l0 = l0 #distance between spheres
        # initial configuration. Usually we just use a straight chain as inital configuration
        self.init_state = np.dstack((np.arange(N),np.zeros(N),np.zeros(N)))[0] #initially set all the coordinates to zeros
        self.state = self.init_state.copy()

        # define a rotation matrix
        # 9 possible rotations: 3 axes * 3 possible rotate angles(45,90,135,180,225,270,315)
        self.rotate_matrix = np.array([[[1,0,0],[0,0,-1],[0,1,0]],[[1,0,0],[0,-1,0],[0,0,-1]]
                                     ,[[1,0,0],[0,0,1],[0,-1,0]],[[0,0,1],[0,1,0],[-1,0,0]]
                                     ,[[-1,0,0],[0,1,0],[0,0,-1]],[[0,0,-1],[0,1,0],[-1,0,0]]
                                     ,[[0,-1,0],[1,0,0],[0,0,1]],[[-1,0,0],[0,-1,0],[0,0,1]]
                                     ,[[0,1,0],[-1,0,0],[0,0,1]],[[x,-x,0],[x,x,0],[0,0,1]]
                                     ,[[1,0,0],[0,x,-x],[0,x,x]]
                                     ,[[x,0,x],[0,1,0],[-x,0,x]],[[-x,-x,0],[x,-x,0],[0,0,1]]
                                     ,[[1,0,0],[0,-x,-x],[0,x,-x]],[[-x,0,x],[0,1,0],[-x,0,-x]]
                                     ,[[-x,x,0],[-x,-x,0],[0,0,1]],[[1,0,0],[0,-x,x],[0,-x,-x]]
                                     ,[[-x,0,-x],[0,1,0],[x,0,-x]],[[x,x,0],[-x,x,0],[0,0,1]]
                                     ,[[1,0,0],[0,x,x],[0,-x,x]],[[x,0,-x],[0,1,0],[x,0,x]]])

    # define pivot algorithm process where t is the number of successful steps
    def walk(self,t): #this definitions helps to start walking in 3d
        acpt = 0
        # while loop until the number of successful step up to t
        while acpt <= t:
            pick_pivot = np.random.randint(1,self.N-1)     # pick a pivot site
            pick_side = np.random.choice([-1,1])           # pick a side
            if pick_side == 1:
                old_chain = self.state[0:pick_pivot+1]
                temp_chain = self.state[pick_pivot+1:]
            else:
                old_chain = self.state[pick_pivot:] # variable to store the coordinates of the old chain
                temp_chain = self.state[0:pick_pivot]# for the temp chain
            # pick a symmetry operator
            symtry_oprtr = self.rotate_matrix[np.random.randint(len(self.rotate_matrix))]     
            # new chain after symmetry operator
            new_chain = np.apply_along_axis(v_dot(symtry_oprtr),1,temp_chain - self.state[pick_pivot]) + self.state[pick_pivot] 
            # use cdist function of scipy package to calculate the pair-pair distance between old_chain and new_chain
            overlap = cdist(new_chain,old_chain) #compare the old chain and the new chain to check if the new chain overlaps on any previous postion

            overlap = overlap.flatten() # just to combine the coordinates in a list which will help to check the overlap

            # determinte whether the new state is accepted or rejected
            if len(np.nonzero(overlap)[0]) != len(overlap):
                continue
            else:
                if pick_side == 1:
                    self.state = np.concatenate((old_chain,new_chain),axis=0)
                elif pick_side == -1:
                    self.state = np.concatenate((new_chain,old_chain),axis=0)
                acpt += 1

        # place the center of mass of the chain on the origin, so then we can translate these coordinates to the initial spread spheres
        self.state = self.l0*(self.state - np.int_(np.mean(self.state,axis=0)))
#now write the coordinates of the spheres in a file
sys.stdout = open("C:\Users\haris\Desktop\CAME_MINE\HIWI\Codes\Temp\Sphere_Positions.txt", "w")
n = 30
#text_file.write("Number of Spheres: " + str(n) + "\n")

#Radius of one sphere: is calculated based on the volume fraction here it 2 percent
r = (3*0.40)/(4*math.pi*n)
#print r
r = r**(1.0/3.0)
#print "Sphere Radius is " + str(r)
sphereList = [] # list to maintain track of the Spheres using their positions
sphereInstancesList = [] # to maintain track of the instances which will be used to cut and or translate the spheres
sphere_pos=[]

#Create n instances of the sphere
#After creating n instances of the sphere we trie to form cluster around each instance of the sphere
for i in range(1, n+1):
    InstanceName = 'Sphere_' + str(i) # creating a name for the instance of the sphere
    #print InstanceName
    #text_file.write(InstanceName)

    #Maximum tries to distribute sphere
    maxTries = 10000000

    while len(sphereList) < i:
        maxTries -= 1
        if maxTries < 1:
            print "Maximum Distribution tries exceded. Error! Restart the Script!"
            break;

        # Make sure Spheres dont cut cube sides: this will place the spheres well inside the cube so that they does'nt touch the sides of the cube 
        # This is done to avoid the periodic boundary condition: later in the next versions it will be used
        vecPosition = [(2*r)+(random.random()*(10.0-r-r-r)),(2*r)+(random.random()*(10.0-r-r-r)),(2*r)+(random.random()*(10.0-r-r-r))]

        sphere_pos.append(vecPosition)
        for pos in sphereList:
            if distance(pos, vecPosition) < 2*r: # checking whether the spheres collide or not
                break
        else:
            sphereList.append(vecPosition)
            print vecPosition
            #text_file.write(str(vecPosition) + "\n")

cluster_Size=[10,12,14,16,18,20,22,24,26,28,30] #list to give the random number of spheres which forms a cluster
for i in range(1,n+1):
    Number_of_Spheres_Clustered=random.choice(cluster_Size) #selecting randomly from the list cluster_Size
    radius_sphr=2*r #Distance between centers of the spheres
    pivot_steps=1000 # for walking the max number of steps
    chain = lattice_SAW(Number_of_Spheres_Clustered,radius_sphr) #initializing the object
    chain.walk(pivot_steps) # calling the walk function to walk in the 3d space
    co_ordinates=chain.state # copying the coordinates into a new variable for processing and converting the coordinates into lists
    for c in range(len(co_ordinates)):
        temp_cds=co_ordinates[c]
        temp_cds=list(temp_cds)        
        for k in range(len(temp_cds)):
            temp_cds[k]=temp_cds[k]+sphere_pos[i-1][k]
        #text_file.write(str(temp_cds) + "\n")
        print temp_cds #sys.stdout redirected into the file which stores the coordinates as lists
sys.stdout.flush()

f2=open("C:\Users\haris\Desktop\CAME_MINE\HIWI\Codes\Temp\Sphere_Positions.txt", "r")
remove_check=[]
for line in f2:
    temp_check=ast.literal_eval(line)
    if (temp_check[0]>10 or temp_check[0]<-r or temp_check[1]>10 or temp_check[1]<-r or temp_check[2]>10 or temp_check[2]<-r):
        remove_check.append(str(temp_check))
f2.close()
flag=0
f2=open("C:\Users\haris\Desktop\CAME_MINE\HIWI\Codes\Temp\Sphere_Positions.txt", "r")
f3=open("C:\Users\haris\Desktop\CAME_MINE\HIWI\Codes\Temp\Sphere_Positions_corrected.txt", "w")
for line in f2:
    line=line.strip()
    if any(line in s for s in remove_check):
        flag=flag+1
    else:
        f3.write(line+'\n')
f3.close()
f2.close()
#代码的功能:1)该代码使用pivot算法实现的自避免随机游动生成球形填料的坐标
#该代码的算法:1)准备一个N步在晶格上行走的初始构型(相当于N个单体链)
#2)沿链随机选择一个站点作为枢轴站点
#3)随机选择一侧(枢轴位置右侧或左侧),此一侧的链条用于下一步。
#4)在我们在上述步骤中选择的链条部分随机应用旋转操作。
#5)旋转后,检查链条旋转部分与链条其余部分之间的重叠。
#6)如果没有重叠,则接受新配置,并从第2步重新启动。
#7)如果存在重叠,则拒绝配置并从第2步开始重复。
################################################################################################################################################################
#要导入的模块如下所示
将numpy作为np导入
导入时间信息
从scipy.spatial.distance导入cdist
输入数学
随机输入
导入系统
导入ast
#定义用于旋转操作的点积函数
定义v_点(a):返回λb:np.点(a,b)
定义距离(x,y):#初始展开球体的欧几里德距离
如果len(x)!=len(y):
raise VALUE ERROR,“向量长度必须相同”
总和=0
对于范围内的i(len(x)):
总和+=(x[i]-y[i])**2
返回math.sqrt(总和)
x=1/数学sqrt(2)
类lattice_SAW:#这是创建自回避随机行走坐标的类
定义初始化(self,N,l0):
self.N=N个球体
self.l0=l0#球体之间的距离
#初始配置。通常我们只使用直链作为初始配置
self.init_state=np.dstack((np.arange(N),np.zeros(N),np.zeros(N))[0]#最初将所有坐标设置为零
self.state=self.init_state.copy()
#定义旋转矩阵
#9个可能的旋转:3个轴*3个可能的旋转角度(45,90135180225270315)
self.rotate_matrix=np.array([[1,0,0],[0,0,-1],[0,1,0],[[1,0,0],[0,-1,0],[0,0,-1]]
,[[1,0,0],[0,0,1],[0,-1,0]],[[0,0,1],[0,1,0],[-1,0,0]]
,[[-1,0,0],[0,1,0],[0,0,-1]],[[0,0,-1],[0,1,0],[-1,0,0]]
,[[0,-1,0],[1,0,0],[0,0,1]],[[-1,0,0],[0,-1,0],[0,0,1]]
,[[0,1,0],[1,0,0],[0,0,1],[x,-x,0],[x,x,0],[0,0,1]]
,[[1,0,0],[0,x,-x],[0,x,x]]
,[[x,0,x],[0,1,0],[x,0,x],[x,-x,0],[x,-x,0],[0,0,1]]
,[[1,0,0],[0,-x,-x],[0,x,-x],[[-x,0,x],[0,1,0],-x,0,-x]]
,[[x,x,0],[x,-x,0],[0,0,1],[1,0,0],[0,-x,x],[0,-x,-x]]
,[-x,0,-x],[0,1,0],[x,0,-x],[[x,x,0],-x,x,0],[0,0,1]]
,[[1,0,0],[0,x,x],[0,-x,x]],[[x,0,-x],[0,1,0],[x,0,x]]
#定义pivot算法过程,其中t是成功步骤数
def walk(self,t):#此定义有助于在3d中开始行走
acpt=0
#while循环,直到成功步进到t的次数

虽然acpt要容纳转角为45135225315的非相交球体(实际上,只有45和315是问题),您只需要将球体稍微缩小一点。连续3个球心,中间有45度转弯。在包含3个点的平面中,该点构成具有45度中心角的等腰三角形:

请注意,底部的圆(球体)重叠。要避免此情况,请将半径乘以系数0.76来缩小:


@gdlmx如果你的随机游动在Z^3晶格(即整数坐标)上,那么你的球体半径太大,你能帮忙吗。需要半径1/2以避免重叠。如果你的随机行走的步长是任意的,那么你就必须计算保持间隔所需的最小半径。@Joseph O'Rourke谢谢你的回答,我的步长是任意的,最初我只有90180270个旋转,我对球体碰撞没有问题。后来我引入了45135225315度的旋转,这就产生了问题。我会尝试你的建议,但可以用一些算法来建议我,比如如何继续,如果我有任意旋转,比如任意旋转,我认为唯一的解决办法是记录你行走的任意两点之间的最小距离,然后使用球体半径此最小值的一半。您是否担心球体重叠的显示,或者重叠是否表示违反了您的自相交标准?谢谢