示例#1
0
    def a1_a2_distance_dist(self,
                            selection_type,
                            selection_1,
                            selection_2,
                            outfilename="distance_dist.dat",
                            cutoff=15.0):
        """
    calculate the distance distribution between selection_1 and selection-2

    selection_type: "atom_name"
    cutoff: ignore distances larger than that

    """
        outfile = open(outfilename, "a")

        if selection_type not in ["atom_name"]:
            print "[ERROR] a1_a2_distance_dist(). Selection type", selection_type, "not recognized!"
            sys.exit()

        for idx_frame, frame in enumerate(self.traj.list_atoms):
            # monitor progress
            if int(len(self.traj.list_atoms) * 0.25) == idx_frame:
                print "         25 % done"
            if int(len(self.traj.list_atoms) * 0.50) == idx_frame:
                print "         50 % done"
            if int(len(self.traj.list_atoms) * 0.75) == idx_frame:
                print "         75 % done   "

            for idx1, atom1 in enumerate(frame):
                for idx2, atom2 in enumerate(frame):
                    if idx2 >= idx1:
                        continue

                    if atom1[self.traj.ATOMNAME] == selection_1 and atom2[
                            self.traj.ATOMNAME] == selection_2:
                        d = pbc.pbc_distance( [atom1[self.traj.X_COORD], atom1[self.traj.Y_COORD], atom1[self.traj.Z_COORD]], \
                                              [atom2[self.traj.X_COORD], atom2[self.traj.Y_COORD], atom2[self.traj.Z_COORD]], \
                                              self.traj.lattice_vector_1, \
                                              self.traj.lattice_vector_2, \
                                              self.traj.lattice_vector_3  )

                        if d * 10.0 < cutoff:
                            outfile.write(str(d * 10.0) + "\n")

        outfile.close()
示例#2
0
##########################################################################################
"""
 ase is a sh*t tool and makes a complete mess in the way it orders the molecules!
 we therefore have to explicitly find atoms that form a water molecule
"""

list_SOL = []
for atom_O in file_poscar.list_atoms:
    if atom_O[file_poscar.ATOMNAME] == "O":
        list_H_idx = []
        list_X_idx = []
        for idx, atom in enumerate(file_poscar.list_atoms):
            if atom[file_poscar.ATOMNAME] == "H":
                d = pbc_distance( [atom_O[file_poscar.X_COORD], atom_O[file_poscar.Y_COORD], atom_O[file_poscar.Z_COORD]],           \
                                  [atom[file_poscar.X_COORD], atom[file_poscar.Y_COORD], atom[file_poscar.Z_COORD]],                 \
                                  file_poscar.lattice_vector_1, \
                                  file_poscar.lattice_vector_2, \
                                  file_poscar.lattice_vector_3  )

                if d < 1.2:
                    list_H_idx.append(idx)

            elif atom[file_poscar.ATOMNAME] == "X":
                d = pbc_distance( [atom_O[file_poscar.X_COORD], atom_O[file_poscar.Y_COORD], atom_O[file_poscar.Z_COORD]],           \
                                  [atom[file_poscar.X_COORD], atom[file_poscar.Y_COORD], atom[file_poscar.Z_COORD]],                 \
                                  file_poscar.lattice_vector_1, \
                                  file_poscar.lattice_vector_2, \
                                  file_poscar.lattice_vector_3  )

                if d < 0.5:
                    list_X_idx.append(idx)
示例#3
0
    def MSD ( self,            \
              outfilename="",  \
              skip_frames=50,  \
              timestep=1.0     ) :
        """
    calculates the MSD

    here the number of particles has to be constant 
      --> we can only apply this to all water molecules in trajectory
    and not for example a subset (such as water in first L

    for more info check:
    http://utkstair.org/clausius/docs/che548/pdf/selfD.pdf

    some technical details:
      Np        ... number of particles
      Nt        ... number of time frames
      No        ... = int(Nt/2): number of considererd origins
                    this also specifies for how many future timesteps will be considered
                    
                    this way every delta_t has the same number of datapoints
                    which means that all of them are equally weighted

      e.g. Nt: 1 2 3 4 5 6  --> Nt/2=3
      calculate MSD 1-2, 1-3, 1-4, 2-3, 2-4, 2-5, 3-4, 3-5, 3-6
      each delta_t has Nt/2*Np datapoints --> this is generally used to get statistics

    this analysis needs to be performed on one concenated trajectory

    it is assumed that the order of atoms does not change from frame to frame
      to make sure we don't do anything stupid, this is checked on the run

    skip_frames ... skipping this number of frames each time
    timestep    ... timestep between different frames (in fs)
    """

        self.check_traj()

        X = 1
        Y = 2
        Z = 3
        INDEX = 4

        if outfilename == "":
            print "[ERROR]. Please specify the output-filename."
            sys.exit()

        outfile = open(outfilename, "a")

        #---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
        #                            split traj                                                 #
        #---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
        # split trajectory into sub-trajectory containing each skip_frames-th frame
        traj_split = ff.format_xyz()

        traj_split.list_atoms = self.traj.list_atoms[::skip_frames]
        traj_split.n_frames = len(traj_split.list_atoms)

        print "\t(+) split trajectory from", self.traj.n_frames, "frames to", len(
            traj_split.list_atoms), "frames"

        # calculate n_origins
        n_origins = int(traj_split.n_frames / 2)

        # initialize list that saves MSD for each delta_t
        # we will have n_origins datapoints for each origin
        # the simple idea:
        #    list_msd = [0.0] * n_origins
        # does not work!
        # because each element in list changes if you change one (weird?)
        # workaround:
        list_msd = []
        for i in range(n_origins):
            list_msd.append([])

        #---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
        #                            loop over all time origins                                 #
        #---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
        for idx_origin in range(n_origins):
            # monitor progress
            if int(n_origins * 0.10) == idx_origin:
                print "         10 % done"
            if int(n_origins * 0.20) == idx_origin:
                print "         20 % done"
            if int(n_origins * 0.30) == idx_origin:
                print "         30 % done   "
            if int(n_origins * 0.40) == idx_origin:
                print "         40 % done"
            if int(n_origins * 0.50) == idx_origin:
                print "         50 % done"
            if int(n_origins * 0.60) == idx_origin:
                print "         60 % done   "
            if int(n_origins * 0.70) == idx_origin:
                print "         70 % done   "
            if int(n_origins * 0.80) == idx_origin:
                print "         80 % done   "
            if int(n_origins * 0.90) == idx_origin:
                print "         90 % done   "

            list_reference = []

            #---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
            #                            loop over all relevant timeframes                          #
            #---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
            for idx_frame, frame in enumerate(
                    traj_split.list_atoms[idx_origin:idx_origin + n_origins]):

                msd = 0

                for idx_atom, atom in enumerate(frame):
                    if len(atom) < 5:
                        print "[ERROR]. In MSD procedure. An atom has not the right format"
                        print "         Frame: ", idx_frame, "atom: ", idx_atom
                        print atom
                        sys.exit()

                    # store x0, y0, z0 for first frame
                    if idx_frame == 0:
                        list_reference.append(atom)

                    # calculate MSD for this atom
                    else:
                        # check if trajectory oredered correctly
                        if list_reference[idx_atom][INDEX] != atom[INDEX]:
                            print "[ERROR]. In MSD procedure: the trajectory is ordered incorrectly"
                            sys.exit()

                        p0 = [
                            list_reference[idx_atom][X],
                            list_reference[idx_atom][Y],
                            list_reference[idx_atom][Z]
                        ]
                        p1 = [atom[X], atom[Y], atom[Z]]

                        d = pbc.pbc_distance( p0,                                        \
                                              p1,                                        \
                                              lattice_v_1 = self.traj.lattice_vector_1 , \
                                              lattice_v_2 = self.traj.lattice_vector_2 , \
                                              lattice_v_3 = self.traj.lattice_vector_3 )
                        msd += d**2

                # normalize MSD to number of atoms
                if int(self.traj.n_atoms) != len(frame):
                    print "[ERROR]. In MSD procedure: the number of atoms does not make sense"
                    print self.traj.n_atoms, len(frame)
                    sys.exit()

                msd = msd / int(self.traj.n_atoms)

                # store MSD for correct delta_t value
                #  --> these values are stored in list_msd
                list_msd[idx_frame].append(msd)

        #---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
        #                            MSD analysis done --> write output                         #
        #---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
        # check if list_msd makes sense:
        if len(list_msd) != n_origins:
            print "[ERROR]. In MSD procedure: list_msd has wrong length"
            sys.exit()

        # write column names
        outfile.write("time ")
        for i, datapoint in enumerate(list_msd[0]):
            outfile.write("obs_" + str(i) + " ")
        outfile.write("\n")

        # write data
        for idx, datapoint in enumerate(list_msd):
            outfile.write(str(idx * timestep * skip_frames) + " ")
            for i in datapoint:
                outfile.write(str(i) + " ")
            outfile.write("\n")

        outfile.close()
示例#4
0
    def mobility( self,                  \
                  outfilename="",        \
                  delta_frame=20,        \
                  list_name_select=["O"] ) :
        """
    calculate the mobility of selected particles

    mobility(t) = \frac{1}{N} \sum_{i=1}^{N} [r_i(t+\Delta t) - r_i(t)]^2

    N           ... number of particles (can change from frame to frame)
    delta_frame ... to how far in the future do we compare current position 

    mobility is calculated for each frame

    if particle with same index does not exist at (t) and (t+\Delta t)
      --> don't calculate mobility for that frame and atom

    this analyser requires extra information (index of atom)
    """
        self.check_traj()

        # makros
        NAME = 0
        X = 1
        Y = 2
        Z = 3
        INDEX = 4

        if outfilename == "":
            print "[ERROR]. No outputfilename specified!"
            sys.exit()

        outfile = open(outfilename, "a")

        for idx_frame, frame in enumerate(self.traj.list_atoms):
            # monitor progress
            if int(self.traj.n_frames * 0.25) == idx_frame:
                print "         25 % done"
            if int(self.traj.n_frames * 0.50) == idx_frame:
                print "         50 % done"
            if int(self.traj.n_frames * 0.75) == idx_frame:
                print "         75 % done   "

            d_sum_squared = 0
            n_particles = 0

            for atom in frame:
                if atom[NAME] in list_name_select:
                    # store coords r_i(t)
                    p1 = [atom[X], atom[Y], atom[Z]]
                    p2 = []

                    # look for same atom in frame+delta_frame
                    # if end of traj so that idx_frame+delta_frame does not exist --> continue
                    if idx_frame + delta_frame > (self.traj.n_frames - 1):
                        continue

                    for atom_2 in self.traj.list_atoms[idx_frame +
                                                       delta_frame]:
                        if atom_2[NAME] in list_name_select:
                            if atom_2[INDEX] == atom[INDEX]:
                                p2 = [atom_2[X], atom_2[Y], atom_2[Z]]
                                break

                    # if particle p1 is not there in frame+delta_frame: move on
                    if len(p2) == 0:
                        continue

                    d = pbc.pbc_distance ( p1 = p1,                                   \
                                           p2 = p2,                                   \
                                           lattice_v_1 = self.traj.lattice_vector_1 , \
                                           lattice_v_2 = self.traj.lattice_vector_2 , \
                                           lattice_v_3 = self.traj.lattice_vector_3 )

                    # collect data
                    d_sum_squared += d**2
                    n_particles += 1

            # --- ATOM LOOP DONE ---
            if n_particles > 0:
                outfile.write(str(d_sum_squared / n_particles) + "\n")

        # --- FRAME LOOP DONE ---
        outfile.close()
示例#5
0
    def Hbond_d_alpha(self, outfilename="", list_name_select=["O"]):
        """
    calculate the distribution of bondlenghts and angles
    of selected hydrogen bonds
    """

        self.check_traj()

        # makros
        NAME = 0
        X = 1
        Y = 2
        Z = 3
        INDEX = 4
        LIST_ACCEPTORS = 5
        LIST_DONORS = 6

        # list_donors / list_acceptors
        PARTNER_TYPE = 0
        O_PARTNER = 1
        H_PARTNER = 2

        # check if index-dictionary was created already
        # if not: create it!
        try:
            self.list_dict_idx
        except:
            self.create_idx_dict()

        if outfilename == "":
            print "[ERROR]. No outputfilename specified!"
            sys.exit()

        outfile = open(outfilename, "a")

        for idx_frame, frame in enumerate(self.traj.list_atoms):
            # monitor progress
            if int(self.traj.n_frames * 0.25) == idx_frame:
                print "         25 % done"
            if int(self.traj.n_frames * 0.50) == idx_frame:
                print "         50 % done"
            if int(self.traj.n_frames * 0.75) == idx_frame:
                print "         75 % done   "

            for atom in frame:
                if atom[NAME] in list_name_select:
                    #---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
                    #                            loop over acceptors                                        #
                    #---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
                    for partner in atom[LIST_ACCEPTORS]:
                        #=======================================================================================#
                        #                            bondlength                                                 #
                        #=======================================================================================#
                        p1 = [atom[X], atom[Y], atom[Z]]

                        p2 = [ frame[self.list_dict_idx[idx_frame][int(partner[O_PARTNER])]][X] , \
                               frame[self.list_dict_idx[idx_frame][int(partner[O_PARTNER])]][Y] , \
                               frame[self.list_dict_idx[idx_frame][int(partner[O_PARTNER])]][Z] ]


                        d = pbc.pbc_distance ( p1 = p1,                                   \
                                               p2 = p2,                                   \
                                               lattice_v_1 = self.traj.lattice_vector_1 , \
                                               lattice_v_2 = self.traj.lattice_vector_2 , \
                                               lattice_v_3 = self.traj.lattice_vector_3 )

                        #=======================================================================================#
                        #                            angle                                                      #
                        #=======================================================================================#
                        # p0 is the atom in the middle (p0 - p1 - p2)
                        p0 = [ frame[self.list_dict_idx[idx_frame][int(partner[H_PARTNER])]][X] , \
                               frame[self.list_dict_idx[idx_frame][int(partner[H_PARTNER])]][Y] , \
                               frame[self.list_dict_idx[idx_frame][int(partner[H_PARTNER])]][Z] ]

                        angle = pbc.pbc_angle ( p0 = p0,                                   \
                                                p1 = p1,                                   \
                                                p2 = p2,                                   \
                                                lattice_v_1 = self.traj.lattice_vector_1 , \
                                                lattice_v_2 = self.traj.lattice_vector_2 , \
                                                lattice_v_3 = self.traj.lattice_vector_3 )

                        outfile.write(str(d) + "   " + str(angle) + "\n")

                    #---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
                    #                            loop over donors                                           #
                    #---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
                    for partner in atom[LIST_DONORS]:
                        #=======================================================================================#
                        #                            bondlength                                                 #
                        #=======================================================================================#
                        p1 = [atom[X], atom[Y], atom[Z]]

                        p2 = [ frame[self.list_dict_idx[idx_frame][int(partner[O_PARTNER])]][X] , \
                               frame[self.list_dict_idx[idx_frame][int(partner[O_PARTNER])]][Y] , \
                               frame[self.list_dict_idx[idx_frame][int(partner[O_PARTNER])]][Z] ]


                        d = pbc.pbc_distance ( p1 = p1,                                   \
                                               p2 = p2,                                   \
                                               lattice_v_1 = self.traj.lattice_vector_1 , \
                                               lattice_v_2 = self.traj.lattice_vector_2 , \
                                               lattice_v_3 = self.traj.lattice_vector_3 )

                        #=======================================================================================#
                        #                            angle                                                      #
                        #=======================================================================================#
                        # p0 is the atom in the middle (p0 - p1 - p2)
                        p0 = [ frame[self.list_dict_idx[idx_frame][int(partner[H_PARTNER])]][X] , \
                               frame[self.list_dict_idx[idx_frame][int(partner[H_PARTNER])]][Y] , \
                               frame[self.list_dict_idx[idx_frame][int(partner[H_PARTNER])]][Z] ]

                        angle = pbc.pbc_angle ( p0 = p0,                                   \
                                                p1 = p1,                                   \
                                                p2 = p2,                                   \
                                                lattice_v_1 = self.traj.lattice_vector_1 , \
                                                lattice_v_2 = self.traj.lattice_vector_2 , \
                                                lattice_v_3 = self.traj.lattice_vector_3 )

                        outfile.write(str(d) + "   " + str(angle) + "\n")

        outfile.close()
示例#6
0
    print "         n_O, n_H and n_X do not have the correct ratio (assuming O,H,X order)"
    print n_O, n_H, n_X
    sys.exit()

# consistency check #2: is idx_O, idx_O+n_O, idx_O+2*n_O and idx_O+3*n_O a watermolecules?
#   --> we exploit this order down the line, so make sure its OK
#       what can happen is that PBC separate water molecules, in that case: remove them on the fly
for idx, atom in enumerate(file_poscar.list_atoms):
    if atom[file_poscar.ATOMNAME] == "O":

        # --- distance to HW1 ---
        d = pbc_distance( [ atom[file_poscar.X_COORD],                              \
                            atom[file_poscar.Y_COORD],                              \
                            atom[file_poscar.Z_COORD] ],                            \
                          [ file_poscar.list_atoms[idx+n_O][file_poscar.X_COORD],   \
                            file_poscar.list_atoms[idx+n_O][file_poscar.Y_COORD],   \
                            file_poscar.list_atoms[idx+n_O][file_poscar.Z_COORD] ], \
                          file_poscar.lattice_vector_1,                             \
                          file_poscar.lattice_vector_2,
                          file_poscar.lattice_vector_3)

        if d > 1.5:
            print "[ERROR]. O ( idx:", idx, ") and H1 ( idx:", n_O + idx, ") are expected to belong to the same water molecule."
            print "         They are too far away from each other however, d=", d
            sys.exit()

        # --- distance to HW2 ---
        d = pbc_distance( [ atom[file_poscar.X_COORD],                                \
                            atom[file_poscar.Y_COORD],                                \
                            atom[file_poscar.Z_COORD] ],                              \
                          [ file_poscar.list_atoms[idx+2*n_O][file_poscar.X_COORD],   \