示例#1
0
 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)
示例#2
0
    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
示例#3
0
 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)
示例#4
0
    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
        ]
示例#7
0
    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
示例#8
0
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