def setUp(self): system = arb() system.system_properties = arb() n = 6 # issue with range(n) => range(6) means 0,1,2,3,4,5 grid_points = np.array([np.array([x,y]) for x in range(n) for y in range(n)]) system.cellspace = DelaunayCellspace(system, grid_points) self.system = system self.boundary = PeriodicBox(system)
def msd(self): """ Calculate MSD and revert boundary conditions or angular mod 2pi """ print("inside msd") arbsys = arb( ) # set up a dummy system... needed to use boundary module... maybe fix this... arbsys.cellspace = DelaunayCellspace( system=arbsys, grid_points=self.system.grid ) ## this is needed to use boundary... not nice boundary = getattr(bedsim.boundary, self.system.boundary)( system=arbsys) # now boundary.delta_dir(r1,r2) can be used data = self.particles.load_dynamics( ) # list of times with list of particles with list of properties a = next( data ) # PROBLEM: at the moment we write pos=0 for t=0 in dynamics which is not good. # FIXME: once this is fixed we don't need to concat the statics data anymore!!!! ####### d0 = next(self.particles.load_statics()) data = [d0] + list( data ) # this is needed, because pos=0 for t=0 in dynamics data! ##### FIXME: REMOVE ONCE DYNAMICS SAVES POSITION PROPERLY FOR t=0!! ##### displacement = [] # i.e. cumulative positions for t1, t2 in self.__pairwise(data): if not t1[0]['pinned'] or t1[0]['pinned'] == 0: disp_per_time = [] for t1p, t2p in zip( t1, t2 ): # iterate over each particle of the two timesteps combined disp_per_time.append( (t1p['cumulative_position'], t2p['cumulative_position'] )) # calc shift during last timestep if displacement != []: dp2 = [] # now calculate the cumulativep position by adding disp_per_time (last shift) to last cumulative position (displacement[-1]) for i, j in zip(displacement[-1], disp_per_time): dp2.append(i + j) displacement.append( dp2) # finally append the cumulative value else: displacement.append(disp_per_time) # calc msd msd = [] for t in displacement: msd_t = 0 for p_traj in t: msd_t += np.dot(p_traj, p_traj) msd.append(msd_t / len(t)) return msd
def setUp(self): #print("\n\n>>> TPB: ") system = arb() system.system_properties = arb() #system.system_properties.boxSize = np.array([2,2]) grid_points = np.array([[0,0], [0,1], [1,1], [1,0], [0,2], [1,2], [2,2], [2,1], [2,0]]) system.cellspace = DelaunayCellspace(system, grid_points) self.system = system self.boundary = PeriodicBox(system)
def load_from_file(self): """ 0. Load file """ bf = BedfileReader(self.config_filename) """ 1. Load system properties """ self.system_properties.summary = bf.system.system_properties """ 2. Load Boundary and cell grid """ self.cellspace = DelaunayCellspace(system=self, grid_points=bf.system.grid) print('hey?') self.boundary = getattr(bedsim.boundary, bf.system.boundary)(system=self) """ 3. Load Particles """ particle_list = next(bf.particles.load_statics()) self._particles = [ getattr(bedsim.particle, p['type'])(**p) for p in particle_list ] """ 4. Update Particles to latest configuration if available """ particles_last = bf.particles.load_last_dynamics() if particles_last is not None: for particle in self._particles: for pl in particles_last: if int(pl['id']) == particle._id: particle.position = pl['position'] particle.angle = pl['angle'] particle.major = pl['major'] particle.minor = pl['minor'] particle.minor2 = pl['minor2'] particle.cumulative_position = pl[ 'cumulative_position'] # LOAD THESE ONLY IF YOU WANT TO RESUME A SIMULATION!! ELSE IT WILL MESS UP THE MSD! # particle.cumulative_angle = pl['cumulative_angle'] # particle.velocity = pl['velocity'] # particle.angvel = pl['angvel'] """ 5. If output filename is not input filename then save initial configuration as well """ if self.config_filename != self.output_filename: self.save_to_file_initial() """ 6. Assign particle to a cell """ [ self.cellspace.assign_particle(particle) for particle in self._particles ]
def plot_cellspace(self): """ Plots the Delaunay triangulation of the cellspace. """ system = arb() self.cellspace = DelaunayCellspace(system=system, grid_points=self.grid_data) if DRAW_CELLS: self.ax.triplot(self.cellspace._grid_points[:, 0], self.cellspace._grid_points[:, 1], self.cellspace.triang.simplices.copy()) self.__grid_to_box_corners() (xmin, xmax, ymin, ymax) = self.__box_corners self.ax.set_xlim(xmin, xmax) self.ax.set_ylim(ymin, ymax) if DRAW_CELL_NEIGHBOURS: ### load boundaries as well to show appropriate neighbours system.cellspace = self.cellspace from bedsim.boundary import PeriodicBox self.boundary = PeriodicBox(system=system) system.boundary = self.boundary ### np.random.seed(3) for cell in self.cellspace.cells: #print("cs = ", cell._simplex) #if (cell._simplex == np.array([15, 21, 16])).all(): #if (cell._simplex == np.array([15, 11, 10])).all(): #if (cell._simplex == np.array([21, 17, 16])).all(): if (cell._simplex == np.array([5, 1, 0])).all(): cell_points = self.cellspace._grid_points[cell._simplex] mpoint = np.sum(cell_points, axis=0) / len(cell_points) for neigh in cell.neighbours: neigh_cell_points = self.cellspace._grid_points[ neigh._simplex] neigh_mpoint = np.sum(neigh_cell_points, axis=0) / len(neigh_cell_points) self.ax.arrow(mpoint[0], mpoint[1], neigh_mpoint[0] - mpoint[0] + np.random.normal(0, 0.1), neigh_mpoint[1] - mpoint[1] + np.random.normal(0, 0.1), head_width=0.05, head_length=0.1, fc='r', ec='r')
def setUp(self): #grid_space = np.linspace(start=-3, stop=3, num=2, endpoint=True).tolist() # num+1 because endpoint counts as well... grid_space = np.linspace( start=-15, stop=15, num=2, endpoint=True).tolist() # num+1 because endpoint counts as well... grid_data = np.array([[x, y] for x in grid_space for y in grid_space]) self.system = System() self.system.cellspace = DelaunayCellspace(system=self.system, grid_points=grid_data) self.system.boundary = getattr(bedsim.boundary, 'PeriodicBox')(system=self.system) e1 = Ellipse(position=[0, 0], velocity=[0, 0], angle=0, angvel=0, major=1, minor=0.5) e2 = Ellipse(position=[1, 1], velocity=[0, 0], angle=0, angvel=0, major=1, minor=0.5) #e1 = Ellipse(position=[0,0], velocity=[0,0], angle=np.pi/4, angvel=0, major = 1, minor = 0.5) #e2 = Ellipse(position=[1.6,0.3], velocity=[0.0000001,0], angle=np.pi/5, angvel=-1*np.pi, major = 1, minor = 0.5) e1._id = 1 e2._id = 2 particles = [e1, e2] self.system._particles = particles ## check if this works [ self.system.cellspace.assign_particle(particle) for particle in self.system._particles ]
def sk_static(self): """ Calculate static distribution function """ arbsys = arb( ) # set up a dummy system... needed to use boundary module... maybe fix this... arbsys.cellspace = DelaunayCellspace( system=arbsys, grid_points=self.system.grid ) ## this is needed to use boundary... not nice boundary = getattr(bedsim.boundary, self.system.boundary)( system=arbsys) # now boundary.delta_dir(r1,r2) can be used data = self.particles.load_dynamics( ) # list of times with list of particles with list of properties # a = next(data) # PROBLEM: at the moment we write pos=0 for t=0 in dynamics which is not good. # FIXME: once this is fixed we don't need to concat the statics data anymore!!!! ####### data = list(data) d0 = data[len(data) - 1] # d0 = next(self.particles.load_statics()) # data = [d0]+list(data) # this is needed, because pos=0 for t=0 in dynamics data! ##### FIXME: REMOVE ONCE DYNAMICS SAVES POSITION PROPERLY FOR t=0!! ##### # nn = len(data) # N = len(data[0]) # number of particles in the system L = 20.92271492899523 # 7.846018098373213 # particle_pairs = product(list(range(N),repeat=2) q_space = np.linspace( start=0, stop=40, num=41, endpoint=True).tolist() # num+1 because endpoint counts as well... q_data = [[float(qx), float(qy), float(qz)] for qx in q_space for qy in q_space for qz in q_space] q_data = np.delete(q_data, 0, 0) sk_static = [] rmin = [] for particle in d0: # get the statistics of the first one if particle['pinned'] == 0: rmin.append(boundary.unwrap(particle['position'])) # start here # seen = set() # seenlist = [] # qlist = [] # # for (qx,qy,qz) in q_data: # normq = np.linalg.norm([qx,qy,qz]) # if normq not in seen: # seen.add(normq) # for (qx,qy,qz) in q_data: # normq = np.linalg.norm([qx,qy,qz]) # ind = seenlist.index(normq) # qlist[ind].append([qx,qy,qz]) # # qlist = deque(qlist) # sk_static = [] # sk = [] # # for sets in qlist: # sets = deque(sets) # mag_q = sets.popleft() # normalized q # rhoq2_per_time = 0. # qnum = len(sets) # while sets: # the remainder is a list of wave vectors # q = sets.popleft() # # rhoq_per_time = (np.sum( [ exp(-1j * np.dot(q,r) * 2*np.pi/L) for r in rmin ] ) ) # cosq = np.sum( np.cos(np.dot(q,r) * 2.*np.pi/L) for r in rmin ) # sinq = np.sum( np.cos(np.dot(q,r) * 2.*np.pi/L) for r in rmin ) # rhoq_per_time = cosq*cosq + sinq*sinq # rhoq2_per_time += rhoq_per_time # # rhoq2_per_time += np.real(rhoq_per_time*np.conj(rhoq_per_time))/len(d0) # sk_static.append([mag_q,rhoq2_per_time/qnum]) # # return sk_static qlist = np.zeros((int(np.sqrt(3. * len(q_space)**2)), 2)) for q in q_data: normq = np.linalg.norm(q) if normq != 0: if normq % 1 == 0: bin = qlist[int(normq)][0] rhoq2_per_time = qlist[int(normq)][1] bin += 1 rhoq_per_time = (np.sum([ exp(-1j * np.dot(q, r) * 2 * np.pi / L) for r in rmin ])) rhoq2_per_time += np.real( rhoq_per_time * np.conj(rhoq_per_time)) / len(d0) qlist[int(normq)][0] = bin qlist[int(normq)][1] = rhoq2_per_time sk_static = [] for (bins, rhos) in qlist.tolist(): if bins != 0: sk_static.append(rhos / bins) else: sk_static.append(rhos) return sk_static
class System(object): """ System base class. """ def simulate(self): """ Start the system dynamics after initialization. Activate event prediction + Event processing """ self.event_manager.start() # FIXME: generalize this ##### if self.cnit != 0: print("mean it: ", self.nit / self.cnit) ### PROFILING INFO!! # FIXME: obsolete... will be calculated in btools package # NOTE: this function here was for testing purposes only during the 'Antrag series' def get_packing_fraction(self): # FIXME: maybe use decorator instead """ FIXME: generalize this! use radius = systemsize/4 NOTE: consider system center I still dont know what this is for. Check the equations :P -A """ center = np.array([1, 1, 1]) # FIXME! => calculate system center from grid! radius = 0.8 # FIXME: use systemsize/4 or systemsize/2 * 0.8 or similar total_volume = 4. * pi * radius**3 / 3. covered_volume = 0 for particle in self._particles: if np.linalg.norm(particle.position - center) <= radius: covered_volume += particle.volume return covered_volume / total_volume def compute_volume_fraction(self): [x, y, z] = self.cellspace._grid_points.transpose() [xmin, xmax, ymin, ymax, zmin, zmax] = [ np.amin(x), np.amax(x), np.amin(y), np.amax(y), np.amin(z), np.amax(z) ] [width, height, depth] = [xmax - xmin, ymax - ymin, zmax - zmin] total_volume = width * height * depth covered_volume = 0 for particle in self._particles: covered_volume += particle.volume( ) # particle.major*particle.minor*particle.minor2 # return covered_volume / total_volume # 4.*np.pi*covered_volume/(total_volume*3) def box_volume(self): [x, y, z] = self.cellspace._grid_points.transpose() [xmin, xmax, ymin, ymax, zmin, zmax] = [ np.amin(x), np.amax(x), np.amin(y), np.amax(y), np.amin(z), np.amax(z) ] [width, height, depth] = [xmax - xmin, ymax - ymin, zmax - zmin] print("inside box volume") return width * height * depth def __get_simbox_packing_fraction(self): [x, y, z] = self.cellspace._grid_points.transpose() [xmin, xmax, ymin, ymax, zmin, zmax] = [ np.amin(x), np.amax(x), np.amin(y), np.amax(y), np.amin(z), np.amax(z) ] [width, height, depth] = [xmax - xmin, ymax - ymin, zmax - zmin] total_volume = width * height * depth covered_volume = 0 for particle in self._particles: covered_volume += particle.volume return covered_volume / total_volume """ IO related methods ================== """ def load_from_file(self): """ 0. Load file """ bf = BedfileReader(self.config_filename) """ 1. Load system properties """ self.system_properties.summary = bf.system.system_properties """ 2. Load Boundary and cell grid """ self.cellspace = DelaunayCellspace(system=self, grid_points=bf.system.grid) print('hey?') self.boundary = getattr(bedsim.boundary, bf.system.boundary)(system=self) """ 3. Load Particles """ particle_list = next(bf.particles.load_statics()) self._particles = [ getattr(bedsim.particle, p['type'])(**p) for p in particle_list ] """ 4. Update Particles to latest configuration if available """ particles_last = bf.particles.load_last_dynamics() if particles_last is not None: for particle in self._particles: for pl in particles_last: if int(pl['id']) == particle._id: particle.position = pl['position'] particle.angle = pl['angle'] particle.major = pl['major'] particle.minor = pl['minor'] particle.minor2 = pl['minor2'] particle.cumulative_position = pl[ 'cumulative_position'] # LOAD THESE ONLY IF YOU WANT TO RESUME A SIMULATION!! ELSE IT WILL MESS UP THE MSD! # particle.cumulative_angle = pl['cumulative_angle'] # particle.velocity = pl['velocity'] # particle.angvel = pl['angvel'] """ 5. If output filename is not input filename then save initial configuration as well """ if self.config_filename != self.output_filename: self.save_to_file_initial() """ 6. Assign particle to a cell """ [ self.cellspace.assign_particle(particle) for particle in self._particles ] # ENABLE IF YOU WANT TO PLOT SYSTEM DURING SIMULATION # self.__plotter.system_sync() # synchronize plotter with system # FIXME: geht schoener... hoffentlich :P def save_to_file_initial(self): # FIXME: change in all clients needed... summary = [particle.get_summary() for particle in self._particles ] # save complete initial state to the statics table # num_timesteps = self.system_properties.lifetime / self.system_properties.summary_timestep + 1 # f = BedfileWriter(filename=self.output_filename, particle_format='ShortFormat', num_timesteps=num_timesteps) f = BedfileWriter(filename=self.output_filename, particle_format='ShortFormat', num_timesteps=None) # only use static methods f.particles.save_statics(data=summary) f.system.system_properties = self.system_properties.summary f.system.boundary = self.boundary.__class__.__name__ f.system.grid = self.cellspace._grid_points # FIXME: save statics even if simulation was not created by a h5 file! def save_to_file(self): """ Saves the current system state to the file provided by 'handle'. @param handle Handle to an hdf file. """ # FIXME: save writer handle on first call timevar = self.system_properties.localtime_round() timestep = round(timevar / self.system_properties.summary_timestep) """ Create summary and save (NEW METHOD) """ summary = [particle.get_summary() for particle in self._particles ] # FIXME: only use dynamics here when changing to full API num_timesteps = self.system_properties.lifetime / self.system_properties.summary_timestep + 1 f = BedfileWriter(filename=self.output_filename, particle_format='ShortFormat', num_timesteps=num_timesteps) #print("where is the file", self.output_filename) #SOPHIA # f.particles.save_dynamics(data=summary, time=timevar) f.particles.save_dynamics(data=summary, time=timestep) f.system.system_properties = self.system_properties.summary # self.__plotter.plot_system("foo_%s.png" % timestep) if self.system_properties.verbose: ## FIXME: maybe remove from save_file and update only after e.g. 2seconds elsewhere self.progress_info() self.write_trajectories() # def __mean_squared_velocity(self): # # check mean squared velocity -> save this to file and don't print to cli # # could be added to saving routine or wherever you want # vs = 0 # for particle in self._particles: # vs += np.dot(particle.velocity,particle.velocity) # print("Deviation ", vs/len(self._particles)) def progress_info(self): """ Prints progress status of the current simulation to stdout. """ progress = round( self.system_properties.localtime_round() / self.system_properties.lifetime * 100, 2) sys.stdout.write("\rSimulation status: %.2f%%" % progress) sys.stdout.flush() def write_trajectories(self): n = len(self._particles) [x, y, z] = self.cellspace._grid_points.transpose() [xmin, xmax, ymin, ymax, zmin, zmax] = [ np.amin(x), np.amax(x), np.amin(y), np.amax(y), np.amin(z), np.amax(z) ] [width, height, depth] = [xmax - xmin, ymax - ymin, zmax - zmin] now = self.system_properties.localtime( ) # or put localtime_round() instead, but for checking this does not help if now == 0: writemode = "w" else: writemode = "a+" OvitoFile = open(self.output_filename + '.dump', writemode) OvitoFile.write('ITEM: TIMESTEP \n') OvitoFile.write(str(now) + '\n') OvitoFile.write('ITEM: NUMBER OF ATOMS \n') OvitoFile.write(str(n) + '\n') OvitoFile.write('ITEM: BOX BOUNDS pp pp pp \n') OvitoFile.write(str(0) + '\t' + str(width) + '\n') OvitoFile.write(str(0) + '\t' + str(height) + '\n') OvitoFile.write(str(0) + '\t' + str(depth) + '\n') OvitoFile.write( 'ITEM: ATOMS id type x y z c_orient[1] c_orient[2] c_orient[3] c_orient[4] c_shape[1] c_shape[2] c_shape[3] \n' ) """ Writing format for quarternion px,py,pz,s """ print("saving file *** time", now) for particle in self._particles: OvitoFile.write( str(int(particle._id)) + '\t' + str(int(particle._id)) + '\t' + str(format(particle.position[0], '.4f')) + '\t' + str(format(particle.position[1], '.4f')) + '\t' + str(format(particle.position[2], '.4f')) + '\t' + str(format(particle.angle[0], '.4f')) + '\t' + str(format(particle.angle[1], '.4f')) + '\t' + str(format(particle.angle[2], '.4f')) + '\t' + str(format(particle.angle[3], '.4f')) + '\t' + str(format(particle.major, '.4f')) + '\t' + str(format(particle.minor, '.4f')) + '\t' + str(format(particle.minor2, '.4f')) + '\n') """ Writing to extra file for MSD calculations SOPHIA """ OvitoFile1 = open(self.output_filename + '.comulative.dump', writemode) OvitoFile1.write('ITEM: TIMESTEP \n') OvitoFile1.write(str(now) + '\n') OvitoFile1.write('ITEM: ATOMS id type x y z \n') for particle in self._particles: OvitoFile1.write( str(int(particle._id)) + '\t' + str(format(particle.cumulative_position[0], '.4f')) + '\t' + str(format(particle.cumulative_position[1], '.4f')) + '\t' + str(format(particle.cumulative_position[2], '.4f')) + '\n') """ Constructor =========== """ def __init__(self, particles=[], system_properties=None): self.nit = 0 self.cnit = 0 self.config_filename = None self.output_filename = None self._particles = particles # save for quick reference, instead of traversing self.cellspace.cells[].particles if system_properties is not None: self.system_properties = system_properties else: self.system_properties = SystemProperties(self) self.event_manager = EventManager( self) # FIXME: generalize this! (Goal 2) self.cellspace = None self.boundary = None