2016-05-25 5 views
5

Ich arbeitete an einem Problem aus den letzten Tagen, Es ist mit der Schaffung eines Selbst Vermeidung von zufälligen Wanderungen mit Pivot-Algorithmus und dann einen anderen Code zu implementieren, der sphärische Einschlüsse platziert in einem 3d Gitter. Ich habe zwei Codes geschrieben, wobei ein Code Koordinaten der Kugeln erzeugt, indem ich einen Zufallslaufalgorithmus verwendet und dann ein anderer Code die Koordinaten verwendet, die vom ersten Programm erzeugt wurden, und dann ein 3d-Gitter in Abaqus mit sphärischen Einschlüssen in ihm erzeugt.Selbst Vermeidung von zufälligen Spaziergang in einem 3d-Gitter mit Pivot-Algorithmus in Python

Das Ergebnis, welches nach dem Ausführen des Codes erzeugt wird: Result which i got

Jetzt ist die in Abschnitt gezoomt (rot Grenze markiert) enter image description here

Problem: Die erzeugten Kugeln miteinander verschmelzen, Wie ich das vermeiden kann, sind mir die Ideen ausgegangen. Ich brauche nur eine Richtung oder einen Algorithmus, um an zu arbeiten.

Der Code, i ist wie folgt geschrieben: Code 1: erzeugt die Koordinaten der

# 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() 

der andere Code Kugeln nicht erforderlich wäre, da es keine Geometrieberechnung in dem zweiten Code ist. Jede Hilfe oder eine Anleitung, wie die Kollision von Kugeln zu vermeiden, ist sehr hilfreich, Vielen Dank alle

+0

@gdlmx kann Ihnen helfen, mit diesem – ayaan

+0

Wenn Irrfahrt auf der Z^3 Gitter (dh ganzzahligen Koordinaten), dann haben Sie einfach die Kugelradien zu groß. Der Radius 1/2 wird benötigt, um Überlappungen zu vermeiden. Wenn Ihr zufälliger Schritt eine beliebige Schrittlänge hat, müssen Sie den minimalen Radius berechnen, der für die Trennung erforderlich ist. –

+0

@ Joseph O'Rourke Danke für die Antwort, Meine Schrittlängen sind willkürlich und anfänglich, wenn ich nur 90.180.270 Umdrehungen habe, hatte ich kein Problem mit den Kugeln, die kollidieren. Ich habe später 45.135.225.315 Grad für die Rotation eingeführt, die das Problem verursacht haben. Ich werde Ihren Vorschlag ausprobieren, aber kann mir eine Art Algorithmus vorschlagen, wie ich vorgehen soll, wenn ich willkürliche Drehungen wie jede mögliche Drehung habe – ayaan

Antwort

2

Um nicht durchschneidende Kugeln mit Drehungen von 45.135.225.315 (wirklich, nur 45 und 315 Probleme) unterzubringen, müssen Sie nur Mach deine Kugeln ein bisschen kleiner. Nehmen Sie 3 aufeinanderfolgende Kugelzentren mit einer Drehung von 45 Grad in der Mitte. In der Ebene der 3 Punkte enthält, das macht ein gleichschenkliges Dreieck mit einem 45-Grad-Zentriwinkel:

overlapping spheres

anzumerken, dass die unteren Kreise (Kugeln) überlappen. Um dies zu vermeiden, schrumpfen Sie den Radius um einen Faktor von 0,76 durch Multiplikation:

smaller spheres

+0

danke für die Antwort, ich werde es versuchen und kommentieren zurück – ayaan

+0

Es half ein bisschen, aber immer noch einige Kollision von Kugeln finden ... Ich versuche es Um es anders zu machen ... Ich werde die Antwort aktualisieren, sobald ich es verstanden habe – ayaan