示例#1
0
    def __init__(self, inputfile, *arg):
        self.inputfile = inputfile
        d = readdump(self.inputfile)
        d.read_onefile()

        self.ParticleNumber     = d.ParticleNumber[0] 
        if d.ParticleNumber[0] != d.ParticleNumber[-1]:
            raise ValueError('************* Paticle Number Changes **************')
        self.ParticleType   = d.ParticleType
        self.Positions      = d.Positions
        self.SnapshotNumber = d.SnapshotNumber
        self.Boxlength      = d.Boxlength[0][:2]
        if not (d.Boxlength[0][:2] == d.Boxlength[-1][:2]).all():
            raise ValueError('*********Box Length Changed from Dump***********')
        self.Boxbounds  = d.Boxbounds[0][:2]
        self.Volume     = self.Boxlength[0] * self.Boxlength[1]
        self.rhototal   = self.ParticleNumber / self.Volume #number density of the total system
        self.typecounts = np.unique(self.ParticleType[0], return_counts = True) 
        self.Type       = self.typecounts[0]
        self.TypeNumber = self.typecounts[1]
        self.rhotype    = self.TypeNumber / self.Volume
        print ('self.Type:', self.Type)
        print ('self.TypeNumber:', self.TypeNumber)
        if np.sum(self.TypeNumber) != self.ParticleNumber:
            raise ValueError('****** Sum of Indivdual Types is Not the Total Amount*******')
示例#2
0
    def __init__(self, dumpfile, Neighborfile, *arg):
        self.dumpfile = dumpfile
        d = readdump(self.dumpfile, 2)  #only at two dimension
        self.Neighborfile = Neighborfile
        d.read_onefile()

        self.TimeStep = d.TimeStep[1] - d.TimeStep[0]
        if self.TimeStep != d.TimeStep[-1] - d.TimeStep[-2]:
            raise ValueError(
                '*********** dump interval changes **************')
        self.ParticleNumber = d.ParticleNumber[0]
        if d.ParticleNumber[0] != d.ParticleNumber[-1]:
            raise ValueError(
                '************* Paticle Number Changes **************')
        self.ParticleType = d.ParticleType
        self.Positions = np.array(d.Positions)
        self.SnapshotNumber = d.SnapshotNumber
        self.Boxlength = d.Boxlength[0]
        if not (d.Boxlength[0] == d.Boxlength[-1]).all():
            raise ValueError(
                '*********Box Length Changed from Dump***********')
        self.rhototal = self.ParticleNumber / np.prod(self.Boxlength)
        self.hmatrix = d.hmatrix
        self.typecounts = np.unique(self.ParticleType[0], return_counts=True)
        self.Type = self.typecounts[0]
        self.TypeNumber = self.typecounts[1]
        print('Particle Type:', self.Type)
        print('Particle TypeNumber:', self.TypeNumber)
        if np.sum(self.TypeNumber) != self.ParticleNumber:
            raise ValueError(
                '****** Sum of Indivdual Types is Not the Total Amount*******')
示例#3
0
文件: Voronoi.py 项目: jungle15/CSDAP
def get_input(inputfile, ndim, radii, filetype = 'lammps', moltypes = ''):
    """ Design input file for Voro++ by considering particle radii 
        radii must be a dict like {1 : 1.28, 2 : 1.60}
        if you do not want to consider radii, set the radii the same

        The keyword filetype is used for different MD engines
        It has four choices:
        'lammps' (default)

        'lammpscenter' (lammps molecular dump with known atom type of each molecule center)
        moltypes is a dict mapping center atomic type to molecular type
        moltypes is also used to select the center atom 
        such as moltypes = {3: 1, 5: 2}

        'gsd' (HOOMD-blue standard output for static properties)
        
        'gsd_dcd' (HOOMD-blue outputs for static and dynamic properties)

    """

    d = readdump(inputfile, ndim, filetype, moltypes)
    d.read_onefile()
    results = []
    for n in range(d.SnapshotNumber):
        ParticleRadii = np.array(pd.Series(d.ParticleType[n]).map(radii))
        PositionRadii = np.column_stack((d.Positions[n], ParticleRadii))
        voroinput     = np.column_stack((np.arange(d.ParticleNumber[n]) + 1, PositionRadii))
        results.append(voroinput)

    return (results, d.Boxbounds)
示例#4
0
    def __init__(self, inputfile, ndim, *arg):
        self.inputfile = inputfile
        self.ndim = ndim
        d = readdump(self.inputfile, self.ndim)
        d.read_onefile()

        self.TimeStep = d.TimeStep[1] - d.TimeStep[0]
        if self.TimeStep != d.TimeStep[-1] - d.TimeStep[-2]:
            raise ValueError(
                '*********** dump interval changes **************')
        self.ParticleNumber = d.ParticleNumber[0]
        if d.ParticleNumber[0] != d.ParticleNumber[-1]:
            raise ValueError(
                '************* Paticle Number Changes **************')
        self.ParticleType = d.ParticleType
        self.Positions = d.Positions
        self.SnapshotNumber = d.SnapshotNumber
        self.Boxlength = d.Boxlength[0]
        if not (d.Boxlength[0] == d.Boxlength[-1]).all():
            raise ValueError(
                '*********Box Length Changed from Dump***********')
        self.Boxbounds = d.Boxbounds[0]
        self.typecounts = np.unique(self.ParticleType[0], return_counts=True)
        self.Type = self.typecounts[0]
        self.TypeNumber = self.typecounts[1]
        print('Particle Type:', self.Type)
        print('Particle TypeNumber:', self.TypeNumber)
        if np.sum(self.TypeNumber) != self.ParticleNumber:
            raise ValueError(
                '****** Sum of Indivdual Types is Not the Total Amount*******')
    def __init__(self, inputfile, *arg):
        self.inputfile = inputfile
        d = readdump(self.inputfile)
        d.read_onefile()

        self.ParticleNumber     = d.ParticleNumber[0] 
        if d.ParticleNumber[0] != d.ParticleNumber[-1]:
            raise ValueError('************* Paticle Number Changes **************')
        self.ParticleType   = d.ParticleType
        self.Positions      = d.Positions
        self.SnapshotNumber = d.SnapshotNumber
        self.Boxlength      = d.Boxlength[0][:2]
        if not (d.Boxlength[0] == d.Boxlength[-1]).all():
            raise ValueError('*********Box Length Changed from Dump***********')
        if len(np.unique(self.Boxlength)) != 1:
            raise ValueError('*********Box is not Cubic***********************')
        self.twopidl    = 2 * pi / self.Boxlength[0]  
        self.Boxbounds  = d.Boxbounds[0][:2]
        self.typecounts = np.unique(self.ParticleType[0], return_counts = True) 
        self.Type       = self.typecounts[0]
        self.TypeNumber = self.typecounts[1]
        print ('self.Type:', self.Type)
        print ('self.TypeNumber:', self.TypeNumber)
        if np.sum(self.TypeNumber) != self.ParticleNumber:
            raise ValueError('****** Sum of Indivdual Types is Not the Total Amount*******')
示例#6
0
def logOrderlife(dumpfile, orderings, ndim = 3, dt = 0.002, outputfile = ''):
    """Calculate the time decay of structural ordering with 
    the initial configuration as reference

    orders is the numpy array of structural ordering
    its shape is [atom_number, snapshot_number]
    this is the standard output format of this analysis package:
    READ: orders = np.loadtxt(orderfile, skiprows = 1)[:, 1:]

    dumpfile is used to get the time scale
    """

    print ('------------Calculate LOG Order time self-correlation---------')
    d = readdump(dumpfile, ndim)
    d.read_onefile()

    if d.SnapshotNumber != orderings.shape[1]:
        errorinfo = '***inconsistent number of configurations and orderings***'
        raise ValueError

    results = np.zeros((d.SnapshotNumber - 1, 2))
    names = 't  St'

    results[:, 0] = (np.array(d.TimeStep[1:]) - np.array(d.TimeStep[0])) * dt 
    CII = orderings[:, 1:] * orderings[:, 0][:, np.newaxis]

    aveS  = np.square(orderings.mean())
    aveS2 = np.square(orderings).mean()
    results[:, 1] = (CII.mean(axis = 0) - aveS) / (aveS2 - aveS)

    if outputfile:
        np.savetxt(outputfile, results, fmt = '%.6f', header = names, comments = '')

    print ('------------Calculate LOG Order time self-correlation Over---------')
    return results, names
示例#7
0
def total_type(inputfile,
               ndim,
               filetype='lammps',
               moltypes='',
               typeid=1,
               qmax=0,
               a=1.0,
               dt=0.002,
               ppp=[1, 1, 1],
               PBC=True,
               outputfile=''):
    """ Compute self-intermediate scattering functions ISF, dynamic susceptibility ISFX4 based on ISF
        Overlap function Qt and its corresponding dynamic susceptibility QtX4
        Mean-square displacements msd; non-Gaussion parameter alpha2
    
        qmax is the wavenumber corresponding to the first peak of structure factor
        a is the cutoff for the overlap function, default is 1.0 (EAM) and 0.3(LJ) (0.3<d>)
        dt is the timestep of MD simulations
        ppp is the periodic boundary conditions
        typeid is the atom type to calculate the properties
        PBC is to determine whether we need to remove periodic boundary conditions

    """
    print(
        '-----------------Compute Overall Dynamics of log output--------------------'
    )

    d = readdump(inputfile, ndim, filetype, moltypes)
    d.read_onefile()

    conditions = d.ParticleType[0] == typeid

    results = np.zeros(((d.SnapshotNumber - 1), 5))
    names = 't  ISF  Qt  msd  alpha2'

    results[:, 0] = (np.array(d.TimeStep[1:]) - d.TimeStep[0]) * dt

    RII = [i[conditions] - d.Positions[0][conditions] for i in d.Positions[1:]]
    RII = np.array(RII)
    if PBC:  #remove PBC
        hmatrixinv = np.linalg.inv(d.hmatrix[0])
        for ii in range(RII.shape[0]):
            matrixij = np.dot(RII[ii], hmatrixinv)
            RII[ii] = np.dot(matrixij - np.rint(matrixij) * ppp, d.hmatrix[0])

    results[:, 1] = (np.cos(RII * qmax).mean(axis=2)).mean(axis=1)
    distance = np.square(RII).sum(axis=2)
    results[:, 2] = (np.sqrt(distance) <= a).sum(axis=1) / conditions.sum()
    results[:, 3] = distance.mean(axis=1)
    distance2 = np.square(distance).mean(axis=1)
    results[:, 4] = alpha2factor(ndim) * distance2 / np.square(
        results[:, 3]) - 1.0

    if outputfile:
        np.savetxt(outputfile, results, fmt='%.6f', header=names, comments='')

    print(
        '-----------------Compute Type Dynamics of log output OVER--------------------'
    )
    return results, names
示例#8
0
    def __init__(self,
                 inputfile,
                 ndim,
                 filetype='lammps',
                 moltypes='',
                 ppp=[1, 1, 1],
                 PBC=True,
                 *arg):
        """
        The keyword filetype is used for different MD engines
        It has four choices:
        'lammps' (default)

        'lammpscenter' (lammps molecular dump with known atom type of each molecule center)
        moltypes is a dict mapping center atomic type to molecular type
        moltypes is also used to select the center atom 
        such as moltypes = {3: 1, 5: 2}

        'gsd' (HOOMD-blue standard output for static properties)
    
        'gsd_dcd' (HOOMD-blue outputs for static and dynamic properties)
        """
        self.inputfile = inputfile
        self.ndim = ndim
        self.filetype = filetype
        self.moltypes = moltypes
        self.ppp = ppp
        self.PBC = PBC
        d = readdump(self.inputfile, self.ndim, self.filetype, self.moltypes)
        d.read_onefile()

        if len(d.TimeStep) > 1:
            self.TimeStep = d.TimeStep[1] - d.TimeStep[0]
            if self.TimeStep != d.TimeStep[-1] - d.TimeStep[-2]:
                print(
                    'Warning: *********** dump interval changes **************'
                )
        self.ParticleNumber = d.ParticleNumber[0]
        if d.ParticleNumber[0] != d.ParticleNumber[-1]:
            print(
                'Warning: ************* Paticle Number Changes **************')
        self.ParticleType = d.ParticleType
        self.Positions = d.Positions
        self.SnapshotNumber = d.SnapshotNumber
        self.Boxlength = d.Boxlength[0]
        if not (d.Boxlength[0] == d.Boxlength[-1]).all():
            print('Warning: *********Box Length Changed from Dump***********')
        self.Boxbounds = d.Boxbounds[0]
        self.typecounts = np.unique(self.ParticleType[0], return_counts=True)
        self.Type = self.typecounts[0].astype(np.int32)
        self.TypeNumber = self.typecounts[1]
        print('Particle Type:', self.Type)
        print('Particle TypeNumber:', self.TypeNumber)
        if np.sum(self.TypeNumber) != self.ParticleNumber:
            print(
                'Warning: ****** Sum of Indivdual Types is Not the Total Amount*******'
            )

        self.hmatrix = d.hmatrix
示例#9
0
def local_tetrahedral_order(dumpfile,
                            filetype='lammps',
                            moltypes='',
                            ppp=[1, 1, 1],
                            outputfile=''):
    """Calcultae local tetrahedral order parameter
        The keyword filetype is used for different MD engines
        It has four choices:
        'lammps' (default)

        'lammpscenter' (lammps molecular dump with known atom type of each molecule center)
        moltypes is a dict mapping center atomic type to molecular type
        moltypes is also used to select the center atom 
        such as moltypes = {3: 1, 5: 2}

        'gsd' (HOOMD-blue standard output for static properties)
    
        'gsd_dcd' (HOOMD-blue outputs for static and dynamic properties)
    """

    d = readdump(dumpfile, 3, filetype, moltypes)
    d.read_onefile()
    num_nearest = 4  #number of selected nearest neighbors
    results = np.zeros((max(d.ParticleNumber), d.SnapshotNumber))

    for n in range(d.SnapshotNumber):
        hmatrixinv = np.linalg.inv(d.hmatrix[n])
        Positions = d.Positions[n]
        for i in range(d.ParticleNumber[n]):
            RIJ = Positions - Positions[i]
            matrixij = np.dot(RIJ, hmatrixinv)
            RIJ = np.dot(matrixij - np.rint(matrixij) * ppp,
                         d.hmatrix[n])  #remove PBC

            RIJ_norm = np.linalg.norm(RIJ, axis=1)
            nearests = np.argpartition(RIJ_norm,
                                       num_nearest + 1)[:num_nearest + 1]
            nearests = [j for j in nearests if j != i]
            for j in range(num_nearest - 1):
                for k in range(j + 1, num_nearest):
                    medium1 = np.dot(RIJ[nearests[j]], RIJ[nearests[k]])
                    medium2 = RIJ_norm[nearests[j]] * RIJ_norm[nearests[k]]
                    results[i, n] += (medium1 / medium2 + 1.0 / 3)**2

    results = np.column_stack(
        (np.arange(d.ParticleNumber[0]) + 1, 1.0 - 3.0 / 8 * results))

    names = 'id q_tetra'
    if outputfile:
        numformat = '%d ' + '%.6f ' * (results.shape[1] - 1)
        np.savetxt(outputfile,
                   results,
                   fmt=numformat,
                   header=names,
                   comments='')

    print('---------calculate local tetrahedral order over---------')
    return results, names
示例#10
0
def partialSq(inputfile,
              selection,
              ndim=3,
              filetype='lammps',
              moltypes='',
              ppp=[1, 1, 1],
              qrange=10,
              outputfile=''):
    """
    calculate the structure factor of a specific group of atoms
    identified by 'selection' of bool type

    The shape of selection must be [num_of_atom, num_of_snapshot]
    """

    print('--------Calculate Conditional S(q)-----------')
    from WaveVector import choosewavevector  #(Numofq, ndim)

    d = readdump(inputfile, ndim, filetype, moltypes)
    d.read_onefile()

    if d.SnapshotNumber != selection.shape[1]:
        errorinfo = '***inconsistent number of configurations and atom selection***'
        raise ValueError(errorinfo)

    twopidl = 2 * np.pi / d.Boxlength[0]
    Numofq = int(qrange / twopidl.max())
    wavevector = choosewavevector(Numofq, ndim)[:, 1:]
    wavevector = wavevector.astype(np.float64) * twopidl[np.newaxis, :]
    wavenumber = np.linalg.norm(wavevector, axis=1)

    sqresults = np.zeros((wavevector.shape[0], 2))
    sqresults[:, 0] = wavenumber

    for n in range(d.SnapshotNumber):
        sqtotal = np.zeros_like(sqresults)
        condition = selection[:, n]
        for i in range(d.ParticleNumber[n]):
            if condition[i]:
                thetas = (d.Positions[n][i][np.newaxis, :] *
                          wavevector).sum(axis=1)
                sqtotal += np.column_stack((np.sin(thetas), np.cos(thetas)))

        sqresults[:, 1] += np.square(sqtotal).sum(
            axis=1) / d.ParticleNumber[n]  #condition.sum() #
    sqresults[:, 1] /= d.SnapshotNumber

    sqresults = pd.DataFrame(sqresults).round(6)
    results = sqresults.groupby(sqresults[0]).mean().reset_index().values

    names = 'q  S(q)'
    if outputfile:
        np.savetxt(outputfile, results, fmt='%.6f', header=names, comments='')

    print('--------Calculate Conditional S(q) OVER-----------')
    return results, names
示例#11
0
文件: Order2D.py 项目: Metison/CSDAP
    def __init__(self, dumpfile, Neighborfile, edgelengthfile='', filetype = 'lammps', moltypes = '', *arg):
        """
        The keyword filetype is used for different MD engines
        It has four choices:
        'lammps' (default)

        'lammpscenter' (lammps molecular dump with known atom type of each molecule center)
        moltypes is a dict mapping center atomic type to molecular type
        moltypes is also used to select the center atom 
        such as moltypes = {3: 1, 5: 2}

        'gsd' (HOOMD-blue standard output for static properties)
    
        'gsd_dcd' (HOOMD-blue outputs for static and dynamic properties)

        edgelengthfile: filename of voronoi cell bonds lengths for each particle
        w.r.t its neighbors, like the face area in 3D. This can be used to weight
        the order parameter; provide False if do not want to weight. (default)
        """
        
        self.dumpfile = dumpfile
        self.filetype = filetype
        self.moltypes = moltypes
        d = readdump(self.dumpfile, 2, self.filetype, self.moltypes) #only at two dimension
        d.read_onefile()
        self.Neighborfile = Neighborfile
        self.edgelengthfile = edgelengthfile

        if len(d.TimeStep) > 1:
            self.TimeStep     = d.TimeStep[1] - d.TimeStep[0]
            if self.TimeStep != d.TimeStep[-1] - d.TimeStep[-2]:
                print ('Warning: *********** dump interval changes **************') 
        self.ParticleNumber     = d.ParticleNumber[0] 
        if d.ParticleNumber[0] != d.ParticleNumber[-1]:
            print ('Warning: ************* Paticle Number Changes **************')
        self.ParticleType   = d.ParticleType
        self.Positions      = np.array(d.Positions)
        self.SnapshotNumber = d.SnapshotNumber
        self.Boxlength      = d.Boxlength[0]
        if not (d.Boxlength[0] == d.Boxlength[-1]).all():
            print ('Warning: *********Box Length Changed from Dump***********')
        self.rhototal   = self.ParticleNumber / np.prod(self.Boxlength)
        self.hmatrix    = d.hmatrix
        self.typecounts = np.unique(self.ParticleType[0], return_counts = True) 
        self.Type       = self.typecounts[0]
        self.TypeNumber = self.typecounts[1]
        print ('Particle Type:', self.Type)
        print ('Particle TypeNumber:', self.TypeNumber)
        if np.sum(self.TypeNumber) != self.ParticleNumber:
            print ('Warning: ****** Sum of Indivdual Types is Not the Total Amount*******')
        
        if self.edgelengthfile:
            print ('----Bond orientational order will be weighted by Voronoi bond lengths----')
        else:
            print ('----Non-weighting is using----')
示例#12
0
def partialgr(inputfile,
              selection,
              ndim=3,
              filetype='lammps',
              moltypes='',
              rdelta=0.01,
              ppp=[1, 1, 1],
              outputfile=''):
    """
    calculate the pair correlation function of a specific group of atoms
    identified by 'selection' of bool type

    The shape of selection must be [num_of_atom, num_of_snapshot]
    """

    print('--------Calculate Conditional g(r)-----------')
    d = readdump(inputfile, ndim, filetype, moltypes)
    d.read_onefile()

    if d.SnapshotNumber != selection.shape[1]:
        errorinfo = '***inconsistent number of configurations and atom selection***'
        raise ValueError(errorinfo)

    MAXBIN = int(d.Boxlength[0].min() / 2.0 / rdelta)
    grresults = np.zeros(MAXBIN)
    for n in range(d.SnapshotNumber):
        hmatrixinv = np.linalg.inv(d.hmatrix[n])
        condition = selection[:, n]
        for i in range(d.ParticleNumber[n] - 1):
            RIJ = d.Positions[n][i + 1:] - d.Positions[n][i]
            matrixij = np.dot(RIJ, hmatrixinv)
            RIJ = np.dot(matrixij - np.rint(matrixij) * ppp,
                         d.hmatrix[n])  #remove PBC
            distance = np.linalg.norm(RIJ, axis=1)
            SIJ = condition[i + 1:] * condition[i]
            Countvalue, BinEdge = np.histogram(distance,
                                               bins=MAXBIN,
                                               range=(0, MAXBIN * rdelta),
                                               weights=SIJ)
            grresults += Countvalue

    binleft = BinEdge[:-1]  #real value of each bin edge, not index
    binright = BinEdge[1:]  #len(Countvalue) = len(BinEdge) - 1
    Nideal = Nidealfac(ndim) * np.pi * (binright**ndim - binleft**ndim)
    rhototal = d.ParticleNumber[0] / np.prod(d.Boxlength[0])
    grresults = grresults * 2 / selection.sum() / (Nideal * rhototal)

    binright = binright - 0.5 * rdelta  #middle of each bin
    results = np.column_stack((binright, grresults))
    names = 'r  g_c(r)'
    if outputfile:
        np.savetxt(outputfile, results, fmt='%.6f', header=names, comments='')

    print('--------Calculate Conditional g(r) OVER-----------')
    return results, names
示例#13
0
def logdynamics(inputfile,
                selection,
                ndim=3,
                filetype='lammps',
                moltypes='',
                qmax=0,
                a=0.3,
                dt=0.002,
                ppp=[1, 1, 1],
                PBC=True,
                outputfile=''):
    """
    calculate the dynamical properties of a specific group of atoms
    identified by 'selection' of bool type

    The shape of selection must be [num_of_atom, num_of_snapshot]
    """

    print('--------Calculate LOG Conditional Dynamics-----------')
    d = readdump(inputfile, ndim, filetype, moltypes)
    d.read_onefile()

    if d.SnapshotNumber != selection.shape[1]:
        print(selection.shape)
        print(
            '--------Warning: selection must be from the initial state---------'
        )

    results = np.zeros(((d.SnapshotNumber - 1), 5))
    names = 't  ISF  Qt  msd  alpha2'

    results[:, 0] = (np.array(d.TimeStep[1:]) - d.TimeStep[0]) * dt

    condition = selection[:, 0]
    RII = [i[condition] - d.Positions[0][condition] for i in d.Positions[1:]]
    if PBC:  #remove PBC
        hmatrixinv = np.linalg.inv(d.hmatrix[0])
        for ii in range(len(RII)):
            matrixij = np.dot(RII[ii], hmatrixinv)
            RII[ii] = np.dot(matrixij - np.rint(matrixij) * ppp, d.hmatrix[0])

    RII = np.array(RII)
    results[:, 1] = (np.cos(RII * qmax).mean(axis=2)).mean(axis=1)
    distance = np.square(RII).sum(axis=2)
    results[:, 2] = (np.sqrt(distance) <= a).mean(axis=1)
    results[:, 3] = distance.mean(axis=1)
    distance2 = np.square(distance).mean(axis=1)
    results[:, 4] = alpha2factor(ndim) * distance2 / np.square(
        results[:, 3]) - 1.0

    if outputfile:
        np.savetxt(outputfile, results, fmt='%.6f', header=names, comments='')

    print('--------Calculate LOG Conditional Dynamics-----------')
    return results, names
示例#14
0
def Nnearests(dumpfile,
              ndim=3,
              filetype='lammps',
              moltypes='',
              N=12,
              ppp=[1, 1, 1],
              fnfile='neighborlist.dat'):
    """Get the N nearest neighbors around a particle
        The keyword filetype is used for different MD engines
        It has four choices:
        'lammps' (default)

        'lammpscenter' (lammps molecular dump with known atom type of each molecule center)
        moltypes is a dict mapping center atomic type to molecular type
        moltypes is also used to select the center atom 
        such as moltypes = {3: 1, 5: 2}

        'gsd' (HOOMD-blue standard output for static properties)
    
        'gsd_dcd' (HOOMD-blue outputs for static and dynamic properties)
    """

    from dump import readdump
    import re

    d = readdump(dumpfile, ndim, filetype, moltypes)
    d.read_onefile()

    fneighbor = open(fnfile, 'w')
    for n in range(d.SnapshotNumber):
        hmatrixinv = np.linalg.inv(d.hmatrix[n])
        Positions = d.Positions[n]
        neighbor = np.zeros((d.ParticleNumber[n], 2 + N), dtype=np.int)
        neighbor[:, 0] = np.arange(d.ParticleNumber[n]) + 1
        neighbor[:, 1] = N

        for i in range(d.ParticleNumber[n]):
            RIJ = Positions - Positions[i]
            matrixij = np.dot(RIJ, hmatrixinv)
            RIJ = np.dot(matrixij - np.rint(matrixij) * ppp,
                         d.hmatrix[n])  #remove PBC

            RIJ_norm = np.linalg.norm(RIJ, axis=1)
            nearests = np.argpartition(RIJ_norm, N + 1)[:N + 1]
            nearests = nearests[RIJ_norm[nearests].argsort()]
            neighbor[i, 2:] = nearests[1:] + 1

        np.set_printoptions(threshold=np.inf, linewidth=np.inf)
        fneighbor.write('id     cn     neighborlist\n')
        fneighbor.write(re.sub('[\[\]]', ' ',
                               np.array2string(neighbor) + '\n'))

    fneighbor.close()
    print('---Calculate %d nearest neighbors done---' % N)
示例#15
0
def cutoffneighbors(dumpfile,
                    r_cut,
                    ndim=3,
                    filetype='lammps',
                    moltypes='',
                    ppp=[1, 1, 1],
                    fnfile='neighborlist.dat'):
    """Get the nearest neighbors around a particle by setting a cutoff distance r_cut
        The keyword filetype is used for different MD engines
        It has four choices:
        'lammps' (default)

        'lammpscenter' (lammps molecular dump with known atom type of each molecule center)
        moltypes is a dict mapping center atomic type to molecular type
        moltypes is also used to select the center atom 
        such as moltypes = {3: 1, 5: 2}

        'gsd' (HOOMD-blue standard output for static properties)
    
        'gsd_dcd' (HOOMD-blue outputs for static and dynamic properties)
    """

    from dump import readdump
    import re

    d = readdump(dumpfile, ndim, filetype, moltypes)
    d.read_onefile()

    fneighbor = open(fnfile, 'w')
    for n in range(d.SnapshotNumber):
        hmatrixinv = np.linalg.inv(d.hmatrix[n])
        Positions = d.Positions[n]
        neighbor = np.arange(d.ParticleNumber[n]).astype(np.int32)
        fneighbor.write('id     cn     neighborlist\n')
        for i in range(d.ParticleNumber[n]):
            RIJ = Positions - Positions[i]
            matrixij = np.dot(RIJ, hmatrixinv)
            RIJ = np.dot(matrixij - np.rint(matrixij) * ppp,
                         d.hmatrix[n])  #remove PBC

            RIJ_norm = np.linalg.norm(RIJ, axis=1)
            nearests = neighbor[RIJ_norm <= r_cut]
            nearests = nearests[RIJ_norm[nearests].argsort()]
            CN = nearests.shape[0] - 1
            fneighbor.write('%d %d ' % (i + 1, CN))
            fneighbor.write(' '.join(map(str, nearests[1:] + 1)))
            fneighbor.write('\n')

#        np.set_printoptions(threshold = np.inf, linewidth = np.inf)
#        fneighbor.write(re.sub('[\[\]]', ' ', np.array2string(neighbor) + '\n'))

    fneighbor.close()
    print('---Calculate nearest neighbors with r_cut = %.6f done---' % r_cut)
示例#16
0
def partialSq(inputfile, selection, ndim = 3, filetype = 'lammps', moltypes = '', ppp = [1,1,1], qrange = 10, outputfile = ''):
    """
    calculate the structure factor of a specific group of atoms
    identified by 'selection' of bool type

    The shape of selection must be [num_of_atom, num_of_snapshot]
    """

    print ('--------Calculate Conditional S(q)-----------')
    from structurefactors import choosewavevector #(Numofq, ndim)

    d = readdump(inputfile, ndim, filetype, moltypes)
    d.read_onefile()

    if d.SnapshotNumber != selection.shape[1]:
        errorinfo = '***inconsistent number of configurations and atom selection***'
        raise ValueError(errorinfo)

    twopidl    = 2 * np.pi / d.Boxlength[0][0]
    Numofq = int(qrange / twopidl)
    wavevector = choosewavevector(Numofq, ndim)
    qvalue, qcount = np.unique(wavevector[:, 0], return_counts = True)
    sqresults = np.zeros((len(wavevector[:, 0]), 2)) #the first row accouants for wavenumber
    for n in range(d.SnapshotNumber):
        sqtotal   = np.zeros((len(wavevector[:, 0]), 2))
        condition = selection[:, n] 
        for i in range(d.ParticleNumber[n]):
            #medium   = twopidl * (d.Positions[n][i] * wavevector[:, 1:]).sum(axis = 1)
            #sqtotal += np.column_stack((np.sin(medium)*condition[i], np.cos(medium)*condition[i]))
            if condition[i]:
                medium   = twopidl * (d.Positions[n][i] * wavevector[:, 1:]).sum(axis = 1)
                sqtotal += np.column_stack((np.sin(medium), np.cos(medium)))

        sqresults[:, 1] += np.square(sqtotal).sum(axis = 1) / condition.sum() #d.ParticleNumber[n]

    sqresults[:, 0]  = wavevector[:, 0]
    sqresults[:, 1]  = sqresults[:, 1] / d.SnapshotNumber

    sqresults = pd.DataFrame(sqresults)
    results   = np.array(sqresults.groupby(sqresults[0]).mean())
    qvalue    = twopidl * np.sqrt(qvalue)
    results   = np.column_stack((qvalue, results))
    names = 'q  S(q)'

    if outputfile:
        np.savetxt(outputfile, results, fmt='%.6f', header = names, comments = '')

    print ('--------Calculate Conditional S(q) OVER-----------')
    return results, names
示例#17
0
def get_input(inputfile, ndim, radii):
    """ Design input file for Voro++ by considering particle radii 
        radii must be a dict like {1 : 1.28, 2 : 1.60}
        if you do not want to consider radii, set the radii the same
    """

    d = readdump(inputfile, ndim)
    d.read_onefile()
    results = []
    for n in range(d.SnapshotNumber):
        ParticleRadii = np.array(pd.Series(d.ParticleType[n]).map(radii))
        PositionRadii = np.column_stack((d.Positions[n], ParticleRadii))
        voroinput = np.column_stack(
            (np.arange(d.ParticleNumber[n]) + 1, PositionRadii))
        results.append(voroinput)

    return (results, d.Boxbounds)
def total(inputfile,
          ndim,
          filetype='lammps',
          moltypes='',
          qmax=0,
          a=1.0,
          dt=0.002,
          outputfile=''):
    """ Compute self-intermediate scattering functions ISF, dynamic susceptibility ISFX4 based on ISF
        Overlap function Qt and its corresponding dynamic susceptibility QtX4
        Mean-square displacements msd; non-Gaussion parameter alpha2
    
        qmax is the wavenumber corresponding to the first peak of structure factor
        a is the cutoff for the overlap function, default is 1.0 (EAM) and 0.3(LJ) (0.3<d>)
        dt is the timestep of MD simulations

    """
    print(
        '-----------------Compute Overall Dynamics of log output--------------------'
    )

    d = readdump(inputfile, ndim, filetype, moltypes)
    d.read_onefile()

    results = np.zeros(((d.SnapshotNumber - 1), 5))
    names = 't  ISF  Qt  msd  alpha2'

    results[:, 0] = (np.array(d.TimeStep[1:]) - d.TimeStep[0]) * dt

    RII = d.Positions[1:] - d.Positions[
        0]  #only use the first configuration as reference
    results[:, 1] = (np.cos(RII * qmax).mean(axis=2)).mean(axis=1)
    distance = np.square(RII).sum(axis=2)
    results[:, 2] = (np.sqrt(distance) <= a).sum(axis=1) / d.ParticleNumber[0]
    results[:, 3] = distance.mean(axis=1)
    distance2 = np.square(distance).mean(axis=1)
    results[:, 4] = alpha2factor(ndim) * distance2 / np.square(
        results[:, 3]) - 1.0

    if outputfile:
        np.savetxt(outputfile, results, fmt='%.6f', header=names, comments='')

    print(
        '-----------------Compute Overall Dynamics of log output OVER--------------------'
    )
    return results, names
示例#19
0
def ConfigOverlap_Single(inputfile, ndim, binsize, outputfile, filetype = 'lammps', moltypes = ''):
    """
     Calculate the overlap of configurations to get the similarity of configurations
        The keyword filetype is used for different MD engines
        It has four choices:
        'lammps' (default)

        'lammpscenter' (lammps molecular dump with known atom type of each molecule center)
        moltypes is a dict mapping center atomic type to molecular type
        moltypes is also used to select the center atom 
        such as moltypes = {3: 1, 5: 2}

        'gsd' (HOOMD-blue standard output for static properties)
    
        'gsd_dcd' (HOOMD-blue outputs for static and dynamic properties)
    """

    d = readdump(inputfile, ndim, filetype, moltypes)
    d.read_onefile()
    positions      = d.Positions
    particlenumber = d.ParticleNumber[0]
    snapshotnumber = d.SnapshotNumber
    boxlength      = d.Boxlength[0] #configurations box should be the same to be compared

    CellNumber     = int( 1.25 * boxlength.max() / binsize) #to embrace the whole box 
    Cell           = np.zeros((CellNumber, CellNumber, CellNumber, snapshotnumber))
    iatom          = np.zeros((particlenumber, ndim, snapshotnumber), dtype = np.int)
    f              = open(outputfile, 'w')
    f.write('overall     selfpart \n')

    for i in range(snapshotnumber):
        iatom[:, :, i] = np.rint(positions[i] / binsize)
        for j in range(particlenumber):
            Cell[iatom[j, 0, i], iatom[j, 1, i], iatom[j, 2, i], i] += 1
        if (Cell > 1).any():
            print ('Warning: More than one atom in a cell, please reduce binsize')

    for i in range(snapshotnumber - 1):
        for j in range(1, snapshotnumber - i):
            overall   = (Cell[iatom[:, 0, i], iatom[:, 1, i], iatom[:, 2, i], i] * 
                         Cell[iatom[:, 0, i], iatom[:, 1, i], iatom[:, 2, i], i + j]).sum() #/ particlenumber
            selfpart  = (Cell[iatom[:, 0, i], iatom[:, 1, i], iatom[:, 2, i], i] == 
                         Cell[iatom[:, 0, i], iatom[:, 1, i], iatom[:, 2, i], i + j]).sum() #/ particlenumber
            f.write('{:.6f}    {:.6f} \n'.format(overall, selfpart))
    f.close()
示例#20
0
def MsdInstant(inputfile,
               ndim,
               filetype='lammps',
               moltypes='',
               everyn=1,
               ppp=[1, 1, 1],
               PBC=True,
               outputfile=''):
    """
    calculate the instantaneous mean squared displacement by
    referencing to the previous 'everyn' configuration
    """

    print('------Compute Instant MSD------')

    d = readdump(inputfile, ndim, filetype, moltypes)
    d.read_onefile()

    results = np.zeros((d.SnapshotNumber - everyn, 2))
    names = 'n imsd'

    results[:, 0] = np.arange(results.shape[0]) + 1

    for n in range(d.SnapshotNumber - everyn):
        RII = d.Positions[n + everyn] - d.Positions[n]
        if PBC:
            hmatrixinv = np.linalg.inv(d.hmatrix[n])
            matrixij = np.dot(RII, hmatrixinv)
            RII = np.dot(matrixij - np.rint(matrixij) * ppp,
                         d.hmatrix[n])  #remove PBC

        results[n, 1] = np.square(RII).sum(axis=1).mean()

    if outputfile:
        unitstep = d.TimeStep[everyn] - d.TimeStep[0]
        np.savetxt(outputfile,
                   results,
                   fmt='%d %.6f',
                   header=names,
                   comments='TimeStep interval:%d\n' % unitstep)

    print('------Compute Instant MSD Over------')
    return results, names
示例#21
0
def Orderlife(dumpfile, orderings, ndim = 3, dt = 0.002, outputfile = ''):
    """Calculate the time decay of structural ordering

    orders is the numpy array of structural ordering
    its shape is [atom_number, snapshot_number]
    this is the standard output format of this analysis package:
    READ: orders = np.loadtxt(orderfile, skiprows = 1)[:, 1:]

    dumpfile is used to get the time scale
    """

    print ('------------Calculate Order time self-correlation---------')
    d = readdump(dumpfile, ndim)
    d.read_onefile()

    TimeStep = d.TimeStep[1] - d.TimeStep[0]
    if TimeStep != d.TimeStep[-1] - d.TimeStep[-2]:
        print ('Warning: ********time interval changes************')

    num_config = orderings.shape[1]
    results = np.zeros((num_config - 1, 2))
    names = 't  St'
    cal_SIt = pd.DataFrame(np.zeros(num_config - 1)[np.newaxis, :]) #time correlation
    deltat  = np.zeros((num_config - 1, 2), dtype = np.int)
    for n in range(num_config - 1):#time interval
        CII = orderings[:, n+1:] * orderings[:, n][:, np.newaxis]
        CII_SIt = CII.mean(axis = 0)
        cal_SIt = pd.concat([cal_SIt, pd.DataFrame(CII_SIt[np.newaxis, :])])

    cal_SIt = cal_SIt.iloc[1:]
    deltat[:, 0] = np.array(cal_SIt.columns) + 1 #time interval
    deltat[:, 1] = np.array(cal_SIt.count())     #time interval frequency

    aveS  = np.square(orderings.mean())
    aveS2 = np.square(orderings).mean()
    results[:, 0] = deltat[:, 0] * TimeStep * dt 
    results[:, 1] = (cal_SIt.mean() - aveS) / (aveS2 - aveS)
    if outputfile:
        np.savetxt(outputfile, results, fmt = '%.6f', header = names, comments = '')

    print ('------------Calculate Order time self-correlation Over---------')
    return results, names
示例#22
0
def cavitation(inputfile, ndim=3, nbin=5, filetype='lammps', moltypes=''):
    """Count atom number in a small bin to see whether cavitation occurs
        The keyword filetype is used for different MD engines
        It has four choices:
        'lammps' (default)

        'lammpscenter' (lammps molecular dump with known atom type of each molecule center)
        moltypes is a dict mapping center atomic type to molecular type
        moltypes is also used to select the center atom 
        such as moltypes = {3: 1, 5: 2}

        'gsd' (HOOMD-blue standard output for static properties)
    
        'gsd_dcd' (HOOMD-blue outputs for static and dynamic properties)
    """

    #get the coordinate information
    d = readdump(inputfile, ndim, filetype, moltypes)
    d.read_onefile()

    if ndim == 3:
        results = np.zeros((nbin + 1, nbin + 1, nbin + 1))
        for i in range(d.SnapshotNumber):
            #remove the original point to be (0, 0, 0)
            newpositions = d.Positions[i] - d.Boxbounds[i][:, 0]
            binsize = (d.Boxlength[i] / nbin)[np.newaxis, :]
            if i == 0: binvolume = np.prod(binsize)
            indices, counts = np.unique(np.rint(newpositions / binsize),
                                        axis=0,
                                        return_counts=True)
            indices = indices.astype(np.int)
            for j in range(indices.shape[0]):
                results[indices[j][0], indices[j][1],
                        indices[j][2]] += counts[j]

        results = results / d.SnapshotNumber
        #-----return empty bin number------------------
        return results.size - np.count_nonzero(results)
示例#23
0
def cal_vector(filename, num_patch=12, ndim=3, ppp=[1, 1, 1]):
    """
    calculate the rotational vectors of each particle considering each patch
    """

    #-----get configuration information-----
    d = readdump(filename, ndim)
    d.read_onefile()
    num_atom = [int(i / (num_patch + 1)) for i in d.ParticleNumber]

    #-----get vector information-------
    fdump = open(filename, 'r')
    pos_all = []  #list of center and patch positions
    for n in range(d.SnapshotNumber):
        medium = np.zeros((num_atom[n], int(1 + num_patch), ndim))
        #three dimensional array for both center and patch positions
        #the first is the center
        for i in range(9):
            fdump.readline()
        for i in range(num_atom[n]):  #also the number of blocks
            for j in range(1 + num_patch):
                medium[i, j] = [
                    float(ii) for ii in fdump.readline().split()[2:2 + ndim]
                ]

            #-----remove PBC-------
            halfbox = (d.Boxlength[n] / 2.0)[np.newaxis, :]
            RIJ = medium[i, 0][np.newaxis, :] - medium[i, 1:]
            periodic = np.where(np.abs(RIJ) > halfbox, np.sign(RIJ),
                                0).astype(np.int)
            medium[i, 1:] += periodic * d.Boxlength[n][np.newaxis, :]

        pos_all.append(medium)

    print('--------prepare positions done-------')
    return pos_all, d.SnapshotNumber, num_atom, d.hmatrix
示例#24
0
def PatchVector(filename,
                num_patch=12,
                ndim=3,
                filetype='lammps',
                outputvec='',
                outputdump=''):
    """get the vector of each particle based on its patches


    Two files will be generated:
    1) patch-particle vector for each particle
    2) coordinates of each particle and its first patch as LAMMPS dump format
    """

    #-----get the first patch of each particle-----
    f = open(filename, 'r')
    for i in range(3):
        f.readline()
    num_total = int(f.readline())
    for i in range(5):
        f.readline()

    num_atom = int(num_total / (num_patch + 1))
    print('Atom Number: %d' % num_atom)
    hosts = []
    firstpatch = []
    for i in range(num_atom):
        hosts.append(int(f.readline().split()[0]))
        firstpatch.append(int(f.readline().split()[0]))
        for j in range(num_patch - 1):
            f.readline()
    f.close()

    if hosts[-1] + 1 != firstpatch[0]:
        print('Warning: possible ERROR about particle-patch relation')

    #-----get positions------
    hosts = np.array(hosts) - 1
    firstpatch = np.array(firstpatch) - 1
    d = readdump(filename, ndim, filetype)
    d.read_onefile()

    pos_centers = [i[hosts] for i in d.Positions]
    pos_patches = [i[firstpatch] for i in d.Positions]

    #------move particles inside of box (PBC)--------
    for n in range(d.SnapshotNumber):
        halfbox = d.Boxlength[n].min() / 2.0
        for i in range(num_atom):
            RIJ = pos_centers[n][i] - pos_patches[n][i]
            periodic = np.where(np.abs(RIJ) > halfbox, np.sign(RIJ),
                                0).astype(np.int)
            pos_patches[n][i] += periodic * d.Boxlength[n]

    #-----calculate vectors------------------
    vectors = []
    for n in range(d.SnapshotNumber):
        vectors.append(pos_patches[n] - pos_centers[n])

    print('-------Particle-Patch vector done------')

    #-------output information on vectors--------------
    fvec = open(outputvec, 'w')
    for n in range(d.SnapshotNumber):
        fvec.write('Step %d\n' % d.TimeStep[n])
        fvec.write('Natom %d\n' % num_atom)
        fvec.write('id type vx vy vz\n')
        for j, i in enumerate(hosts):
            fvec.write('%d %d ' % (j + 1, d.ParticleType[n][i]))
            fvec.write('%.6f %.6f %.6f\n' % tuple(vectors[n][j]))
    fvec.close()

    #-------output information on paritcle-patch-------
    if outputdump:
        fdump = open(outputdump, 'w')
        totalnum = num_atom + len(firstpatch)
        for n in range(d.SnapshotNumber):
            header = lammps(d.TimeStep[n], totalnum, d.Boxbounds[n])
            fdump.write(header)
            for j, i in enumerate(hosts):
                fdump.write('%d %d ' % (j + 1, d.ParticleType[n][i]))
                fdump.write('%.6f %.6f %.6f\n' % tuple(d.Positions[n][i]))

            for j, i in enumerate(firstpatch):
                fdump.write('%d %d ' %
                            (num_atom + j + 1, d.ParticleType[n][i]))
                fdump.write('%.6f %.6f %.6f\n' % tuple(d.Positions[n][i]))
        fdump.close()

    print('--------wrting configuration information over--------')
    return None
示例#25
0
def dynamics(inputfile, selection, ndim = 3, filetype = 'lammps', moltypes = '', qmax = 0, a = 0.3, dt = 0.002, ppp = [1,1,1], PBC = True, outputfile = ''):
    """
    calculate the dynamical properties of a specific group of atoms
    identified by 'selection' of bool type

    The shape of selection must be [num_of_atom, num_of_snapshot]
    """

    print ('--------Calculate Conditional Dynamics-----------')
    d = readdump(inputfile, ndim, filetype, moltypes)
    d.read_onefile()

    if d.SnapshotNumber != selection.shape[1]:
        errorinfo = '***inconsistent number of configurations and atom selection***'
        raise ValueError(errorinfo)

    TimeStep = d.TimeStep[1] - d.TimeStep[0]
    if TimeStep != (d.TimeStep[-1] - d.TimeStep[-2]):
        print ('-------Warning: dump interval changes-------')

    results = np.zeros(((d.SnapshotNumber - 1), 5))
    names  = 't  ISF  Qt  msd  alpha2'

    cal_isf  = pd.DataFrame(np.zeros((d.SnapshotNumber-1))[np.newaxis, :])
    cal_Qt   = pd.DataFrame(np.zeros((d.SnapshotNumber-1))[np.newaxis, :])
    cal_msd  = pd.DataFrame(np.zeros((d.SnapshotNumber-1))[np.newaxis, :])
    cal_alp  = pd.DataFrame(np.zeros((d.SnapshotNumber-1))[np.newaxis, :])
    deltat   = np.zeros(((d.SnapshotNumber - 1), 2), dtype = np.int) #deltat, deltatcounts
    for n in range(d.SnapshotNumber - 1): #time interval
        condition  = selection[:, n]
        RII = [i[condition] - d.Positions[n][condition] for i in d.Positions[n+1:]]
        if PBC:#remove PBC
            hmatrixinv = np.linalg.inv(d.hmatrix[n])
            for ii in range(len(RII)):
                matrixij = np.dot(RII[ii], hmatrixinv)
                RII[ii]  = np.dot(matrixij - np.rint(matrixij) * ppp, d.hmatrix[n]) 

        RII = np.array(RII) #shape [deltat, Natom_selected, ndim]
        RII_isf   = (np.cos(RII * qmax).mean(axis = 2)).mean(axis = 1) #index is timeinterval -1
        cal_isf   = pd.concat([cal_isf, pd.DataFrame(RII_isf[np.newaxis, :])])
        distance  = np.square(RII).sum(axis = 2)
        RII_Qt    = (np.sqrt(distance) <= a).mean(axis = 1)
        cal_Qt    = pd.concat([cal_Qt, pd.DataFrame(RII_Qt[np.newaxis, :])])
        cal_msd   = pd.concat([cal_msd, pd.DataFrame(distance.mean(axis = 1)[np.newaxis, :])])
        distance2 = np.square(distance).mean(axis = 1)
        cal_alp   = pd.concat([cal_alp, pd.DataFrame(distance2[np.newaxis, :])])

    cal_isf      = cal_isf.iloc[1:]
    cal_Qt       = cal_Qt.iloc[1:]
    cal_msd      = cal_msd.iloc[1:]
    cal_alp      = cal_alp.iloc[1:]
    deltat[:, 0] = np.array(cal_isf.columns) + 1 #Timeinterval
    deltat[:, 1] = np.array(cal_isf.count())     #Timeinterval frequency

    results[:, 0] = deltat[:, 0] * TimeStep * dt
    results[:, 1] = cal_isf.mean()
    results[:, 2] = cal_Qt.mean()
    results[:, 3] = cal_msd.mean()
    results[:, 4] = cal_alp.mean()
    results[:, 5] = alpha2factor(ndim) * results[:, 4] / np.square(results[:, 3]) - 1.0

    if outputfile:
        np.savetxt(outputfile, results, fmt='%.6f', header = names, comments = '')
    
    print ('--------Calculate Conditional Dynamics OVER-----------')
    return results, names
示例#26
0
def S4(file_positions,
       file_orientations,
       ndim,
       X4time,
       filetype='lammps',
       moltypes='',
       dt=0.002,
       phi=0.2,
       qrange=10,
       outputfile=''):
    """ Compute four-point dynamic structure factor at peak timescale of dynamic susceptibility

        Based on dynamics overlap function CRtotal and its corresponding dynamic susceptibility X4     
        file_positions: atomic positions
        file_orientations: atomic orientations
        phi is the cutoff for the dynamics overlap function
        X4time is the peaktime scale of X4
        dt is the timestep in MD simulations
        Dynamics should be calculated before computing S4
        Only considered the particles which are rotationally slow
    """

    print('-----Compute dynamic S4(q) of rotational slow particles-----')
    from WaveVector import choosewavevector
    from dump import readdump
    from math import pi

    #read positions
    d1 = readdump(file_positions, ndim, filetype, moltypes)
    d1.read_onefile()

    #read orientations
    d2 = readangular(file_orientations, ndim)
    d2.read_onefile()
    #get unit vector
    velocity = [
        u / np.linalg.norm(u, axis=1)[:, np.newaxis] for u in d2.velocity
    ]

    #check files
    if d1.SnapshotNumber != d2.SnapshotNumber:
        print('warning: ******check configurations*****')
    if d1.ParticleNumber[0] != d2.ParticleNumber[0]:
        print('warning: ******check configurations*****')
    if d1.TimeStep[0] != d2.TimeStep[0]:
        print('warning: ******check configurations*****')
    TimeStep = d1.TimeStep[1] - d1.TimeStep[0]
    if TimeStep != d1.TimeStep[-1] - d1.TimeStep[-2]:
        print('Warning: *****time interval changes*****')
    ParticleNumber = d1.ParticleNumber[0]
    if ParticleNumber != d1.ParticleNumber[-1]:
        print('Warning: *****particle number changes*****')

    #calculate dynamics and structure factor
    X4time = int(X4time / dt / TimeStep)

    twopidl = 2 * pi / d1.Boxlength[0]  #list over dimensions
    Numofq = int(qrange / twopidl.max())
    wavevector = choosewavevector(
        Numofq, ndim)[:, 1:]  #Only S4(q) at low wavenumber range is interested
    wavevector = wavevector.astype(
        np.float64) * twopidl[np.newaxis, :]  #considering non-cubic box
    wavenumber = np.linalg.norm(wavevector, axis=1)

    sqresults = np.zeros((wavevector.shape[0], 2))
    sqresults[:, 0] = wavenumber

    for n in range(d1.SnapshotNumber - X4time):
        RII = (velocity[n + X4time] * velocity[n]).sum(axis=1)
        RII = np.where(RII >= phi, 1, 0)

        sqtotal = np.zeros_like(sqresults)
        for i in range(ParticleNumber):
            if RII[i]:
                thetas = (d1.Positions[n][i][np.newaxis, :] *
                          wavevector).sum(axis=1)
                sqtotal[:, 0] += np.sin(thetas)
                sqtotal[:, 1] += np.cos(thetas)

        sqresults[:, 1] += np.square(sqtotal).sum(axis=1) / ParticleNumber
    sqresults[:, 1] /= (d1.SnapshotNumber - X4time)

    sqresults = pd.DataFrame(sqresults).round(6)
    results = sqresults.groupby(sqresults[0]).mean().reset_index().values

    names = 'q  S4'
    if outputfile:
        np.savetxt(outputfile, results, fmt='%.6f', header=names, comments='')

    print('--------- Compute S4(q) of slow particles over ------')
    return results, names
示例#27
0
def Vonmises(inputfile,
             Neighborfile,
             ndim,
             strainrate,
             outputfile,
             ppp=[1, 1, 1],
             dt=0.002,
             results_path='../../analysis/Strain/'):
    """ Calculate Non-Affine Von-Mises Strain (local shear invariant)
        
        With the first snapshot of inputfile as reference
        The unit of strianrate should in align with the intrinsic time unit (i.e with dt)
        The code accounts for both orthogonal and triclinic boxes
    """
    if not os.path.exists(results_path):
        os.makedirs(results_path)

    d = readdump(inputfile, ndim)
    d.read_onefile()
    positions = d.Positions
    particlenumber = d.ParticleNumber[0]
    snapshotnumber = d.SnapshotNumber
    boxlength = d.Boxlength
    hmatrix = d.hmatrix
    timestep = d.TimeStep[1] - d.TimeStep[0]
    PI = np.eye(ndim, dtype=int)  #identity matrix along diag
    results = np.zeros((particlenumber, snapshotnumber - 1))

    fneighbor = open(Neighborfile, 'r')
    Neighborlist = Voropp(fneighbor,
                          particlenumber)  #neighbor list [number, list...]
    fneighbor.close()
    for i in range(particlenumber):
        neighbors = Neighborlist[i, 1:Neighborlist[i, 0] + 1]
        RIJ0 = positions[0][neighbors] - positions[0][
            i]  #reference snapshot: the initial one
        #periodic  = np.where(np.abs(RIJ0 / boxlength[0]) > 0.50, np.sign(RIJ0), 0)
        #RIJ0     -= boxlength[0] * periodic * ppp #remove periodic boundary conditions
        matrixij = np.dot(RIJ0, np.linalg.inv(hmatrix[0]))
        RIJ0 = np.dot(matrixij - np.rint(matrixij) * ppp, hmatrix[0])
        for j in range(snapshotnumber - 1):
            RIJ1 = positions[j + 1][neighbors] - positions[j + 1][
                i]  #deformed snapshot
            matrixij = np.dot(RIJ1, np.linalg.inv(hmatrix[j + 1]))
            RIJ1 = np.dot(matrixij - np.rint(matrixij) * ppp, hmatrix[j + 1])
            PJ = np.dot(np.linalg.inv(np.dot(RIJ0.T, RIJ0)),
                        np.dot(RIJ0.T, RIJ1))
            etaij = 0.5 * (np.dot(PJ, PJ.T) - PI)
            results[i, j] = np.sqrt(0.5 * np.trace(
                np.linalg.matrix_power(
                    etaij - (1 / ndim) * np.trace(etaij) * PI, 2)))

    results = np.column_stack((np.arange(particlenumber) + 1, results))
    strain = np.arange(snapshotnumber) * timestep * dt * strainrate
    results = np.vstack((strain, results))
    names = 'id   The_first_row_is_the_strain.0isNAN'
    fformat = '%d ' + '%.6f ' * (snapshotnumber - 1)
    np.savetxt(results_path + outputfile,
               results,
               fmt=fformat,
               header=names,
               comments='')
    print('------ Calculate Von Mises Strain Over -------')
    return results
示例#28
0
        The keyword filetype is used for different MD engines
        It has four choices:
        'lammps' (default)

        'lammpscenter' (lammps molecular dump with known atom type of each molecule center)
        moltypes is a dict mapping center atomic type to molecular type
        moltypes is also used to select the center atom 
        such as moltypes = {3: 1, 5: 2}

        'gsd' (HOOMD-blue standard output for static properties)
    
        'gsd_dcd' (HOOMD-blue outputs for static and dynamic properties)
    """

    #get the coordinate information
    d = readdump(inputfile, ndim, filetype, moltypes)
    d.read_onefile()

    if ndim == 3: 
        results = np.zeros((nbin + 1, nbin + 1, nbin + 1))
        for i in range(d.SnapshotNumber):
            #remove the original point to be (0, 0, 0)
            newpositions = d.Positions[i] - d.Boxbounds[i][:, 0]
            binsize = (d.Boxlength[i] / nbin)[np.newaxis, :]
            if i == 0: binvolume = np.prod(binsize) 
            indices, counts = np.unique(np.rint(newpositions / binsize), axis = 0, return_counts = True)
            indices = indices.astype(np.int)
            for j in range(indices.shape[0]):
                results[indices[j][0], indices[j][1], indices[j][2]] += counts[j]

        results = results / d.SnapshotNumber
示例#29
0
def Vonmises(inputfile,
             Neighborfile,
             ndim,
             strainrate,
             ppp=[1, 1, 1],
             dt=0.002,
             filetype='lammps',
             moltypes='',
             outputfile=''):
    """ Calculate Non-Affine Von-Mises Strain (local shear invariant)
        
        With the first snapshot of inputfile as reference
        The unit of strianrate should in align with the intrinsic time unit (i.e with dt)
        The code accounts for both orthogonal and triclinic boxes

        The keyword filetype is used for different MD engines
        It has four choices:
        'lammps' (default)

        'lammpscenter' (lammps molecular dump with known atom type of each molecule center)
        moltypes is a dict mapping center atomic type to molecular type
        moltypes is also used to select the center atom 
        such as moltypes = {3: 1, 5: 2}

        'gsd' (HOOMD-blue standard output for static properties)
    
        'gsd_dcd' (HOOMD-blue outputs for static and dynamic properties)
    """

    d = readdump(inputfile, ndim, filetype, moltypes)
    d.read_onefile()
    positions = d.Positions
    particlenumber = d.ParticleNumber[0]
    snapshotnumber = d.SnapshotNumber
    boxlength = d.Boxlength
    hmatrix = d.hmatrix
    timestep = d.TimeStep[1] - d.TimeStep[0]
    PI = np.eye(ndim, dtype=int)  #identity matrix along diag
    results = np.zeros((particlenumber, snapshotnumber - 1))

    fneighbor = open(Neighborfile, 'r')
    Neighborlist = Voropp(fneighbor,
                          particlenumber)  #neighbor list [number, list...]
    fneighbor.close()
    for i in range(particlenumber):
        neighbors = Neighborlist[i, 1:Neighborlist[i, 0] + 1]
        RIJ0 = positions[0][neighbors] - positions[0][
            i]  #reference snapshot: the initial one
        #periodic  = np.where(np.abs(RIJ0 / boxlength[0]) > 0.50, np.sign(RIJ0), 0)
        #RIJ0     -= boxlength[0] * periodic * ppp #remove periodic boundary conditions
        matrixij = np.dot(RIJ0, np.linalg.inv(hmatrix[0]))
        RIJ0 = np.dot(matrixij - np.rint(matrixij) * ppp, hmatrix[0])
        for j in range(snapshotnumber - 1):
            RIJ1 = positions[j + 1][neighbors] - positions[j + 1][
                i]  #deformed snapshot
            matrixij = np.dot(RIJ1, np.linalg.inv(hmatrix[j + 1]))
            RIJ1 = np.dot(matrixij - np.rint(matrixij) * ppp, hmatrix[j + 1])
            PJ = np.dot(np.linalg.inv(np.dot(RIJ0.T, RIJ0)),
                        np.dot(RIJ0.T, RIJ1))
            etaij = 0.5 * (np.dot(PJ, PJ.T) - PI)
            results[i, j] = np.sqrt(0.5 * np.trace(
                np.linalg.matrix_power(
                    etaij - (1 / ndim) * np.trace(etaij) * PI, 2)))

    results = np.column_stack((np.arange(particlenumber) + 1, results))
    strain = np.arange(snapshotnumber) * timestep * dt * strainrate
    results = np.vstack((strain, results))
    names = 'id   The_first_row_is_the_strain.0isNAN'
    fformat = '%d ' + '%.6f ' * (snapshotnumber - 1)
    if outputfile:
        np.savetxt(outputfile, results, fmt=fformat, header=names, comments='')

    print('------ Calculate Von Mises Strain Over -------')
    return results, names
示例#30
0
def neighbortypes(inputfile,
                  ndim,
                  neighborfile,
                  filetype='lammps',
                  moltypes='',
                  outputfile=''):
    """Analysis the fractions of atom A in the first neighbor of atom B
        The keyword filetype is used for different MD engines
        It has four choices:
        'lammps' (default)

        'lammpscenter' (lammps molecular dump with known atom type of each molecule center)
        moltypes is a dict mapping center atomic type to molecular type
        moltypes is also used to select the center atom 
        such as moltypes = {3: 1, 5: 2}

        'gsd' (HOOMD-blue standard output for static properties)
    
        'gsd_dcd' (HOOMD-blue outputs for static and dynamic properties)
    """

    #get the coordinate information
    d = readdump(inputfile, ndim, filetype, moltypes)
    d.read_onefile()
    #get the neighbor list from voronoi analysis
    fneighbor = open(neighborfile, 'r')

    results = np.zeros((d.SnapshotNumber, 3))  #for binary system 11 12/21 22
    for i in range(d.SnapshotNumber):
        neighborlist = Voropp(
            fneighbor, d.ParticleNumber[i])  #neighbor list [number, list....]
        neighbortype = d.ParticleType[i]

        medium = np.zeros(6)
        for j in range(d.ParticleNumber[i]):
            neighborsij = neighborlist[j, 1:(neighborlist[j, 0] + 1)]
            data11 = (neighbortype[j] + neighbortype[neighborsij] == 2).sum()
            if data11 > 0:
                medium[0] += neighborlist[j, 0]
                medium[1] += data11

            data12 = (neighbortype[j] + neighbortype[neighborsij] == 3).sum()
            if data12 > 0:
                medium[2] += neighborlist[j, 0]
                medium[3] += data12

            data22 = (neighbortype[j] + neighbortype[neighborsij] == 4).sum()
            if data22 > 0:
                medium[4] += neighborlist[j, 0]
                medium[5] += data22

        results[i, 0] = medium[1] / medium[0]
        results[i, 1] = medium[3] / medium[2]
        results[i, 2] = medium[5] / medium[4]

    fneighbor.close()
    if outputfile:
        names = '11  12/21  22'
        np.savetxt(outputfile,
                   results,
                   fmt=3 * ' %.6f',
                   header=names,
                   comments='')

    print('-------demix checking over------')
    return results, names