Beispiel #1
0
def print_file_path(mode, beads, cell, filedesc=sys.stdout, title="", key="", dimension="length", units="automatic", cell_units="automatic"):
    """Prints all the bead configurations, into a `mode` formatted file.

    Prints all the replicas for each time step separately, rather than all at
    once.

    Args:
        beads: A beads object giving the bead positions.
        cell: A cell object giving the system box.
        filedesc: An open writable file object. Defaults to standard output.
    """

    if mode == "pdb":   # special case for PDB
        if dimension != "length":
            raise ValueError("PDB Standard is only designed for atomic positions")
        if units == "automatic": units = "angstrom"
        if cell_units == "automatic": cell_units = "angstrom"
    # in general, "automatic" units are actually "atomic_units"
    else:
        if units == "automatic": units = "atomic_unit"
        if cell_units == "automatic": cell_units = "atomic_unit"

    cell_conv = unit_to_user("length", cell_units, 1.0)
    atoms_conv = unit_to_user(dimension, units, 1.0)

    title = title + ("%s{%s}  cell{%s}" % (key, units, cell_units))

    return _get_io_function(mode, "print_path")(beads=beads, cell=cell, filedesc=filedesc, cell_conv=cell_conv, atoms_conv=atoms_conv)
Beispiel #2
0
def print_instanton_geo(prefix, step, nbeads, natoms, names, q, pots, cell, shift, output_maker):

    outfile = output_maker.get_output(prefix + '_' + str(step) + '.ener', 'w')
    print >> outfile, ('#Bead    Energy (eV)')
    for i in range(nbeads):
        print >> outfile, (str(i) + '     ' + str(units.unit_to_user('energy', "electronvolt", pots[i] - shift)))
    outfile.close()

    # print_file("xyz", pos[0], cell, out, title='positions{angstrom}')

    unit = 'angstrom'
    a, b, c, alpha, beta, gamma = mt.h2abc_deg(cell.h)

    outfile = output_maker.get_output(prefix + '_' + str(step) + '.xyz', 'w')
    for i in range(nbeads):
        print >> outfile, natoms

        print >> outfile, ('CELL(abcABC):  %f %f %f %f %f %f cell{atomic_unit}  Traj: positions{%s}   Bead:       %i' % (a, b, c, alpha, beta, gamma, unit, i))

        for j in range(natoms):
            print >> outfile, names[j], \
                str(units.unit_to_user('length', unit, q[i, 3 * j])), \
                str(units.unit_to_user('length', unit, q[i, 3 * j + 1])), \
                str(units.unit_to_user('length', unit, q[i, 3 * j + 2]))

    outfile.close()
Beispiel #3
0
def print_file(mode, atoms, cell, filedesc=sys.stdout, title="", key="", dimension="length", units="automatic", cell_units="automatic"):
    """Prints atom positions, or atom-vector properties, into a `mode` formatted file,
       using i-PI internal representation of atoms & cell. Does conversion and prepares
       formatted title line.

    Args:
        mode: I/O file format (e.g. "xyz")
        atoms: An atoms object containing the positions (or properties) of the atoms
        cell: A cell object containing the system box.
        filedesc: An open writable file object. Defaults to standard output.
        title: This gives a string to be appended to the comment line.
        key: Description of the property that is being output
        dimension: Dimensions of the property (e.g. "length")
        units: Units for the output (e.g. "angstrom")
        cell_units: Units for the cell (dimension length, e.g. "angstrom")
    """
    if mode == "pdb":   # special case for PDB
        if dimension != "length":
            raise ValueError("PDB Standard is only designed for atomic positions")
        if units == "automatic": units = "angstrom"
        if cell_units == "automatic": cell_units = "angstrom"
        if key == "": key = "positions"
    # in general, "automatic" units are actually "atomic_units"
    else:
        if units == "automatic": units = "atomic_unit"
        if cell_units == "automatic": cell_units = "atomic_unit"

    cell_conv = unit_to_user("length", cell_units, 1.0)
    atoms_conv = unit_to_user(dimension, units, 1.0)

    title = title + ("%s{%s}  cell{%s}" % (key, units, cell_units))
    print_file_raw(mode=mode, atoms=atoms, cell=cell, filedesc=filedesc, title=title, cell_conv=cell_conv, atoms_conv=atoms_conv)
Beispiel #4
0
    def __init__(self, init_file, args_str, param_file, latency=1.0e-3, name="", pars=None, dopbc=True, threaded=False):
        """Initialises QUIP.

        Args:
        pars: Mandatory dictionary, giving the parameters needed by QUIP.
        """
        if quippy is None:
            info("QUIPPY import failed", verbosity.low)
            raise quippy_exc

        # a socket to the communication library is created or linked
        super(FFQUIP, self).__init__(latency, name, pars, dopbc, threaded=threaded)
        self.init_file = init_file
        self.args_str = args_str
        self.param_file = param_file

        # Initializes an atoms object and the interaction potential
        self.atoms = quippy.Atoms(self.init_file)
        self.pot = quippy.Potential(self.args_str, param_filename=self.param_file)

        # Initializes the conversion factors from i-pi to QUIP
        self.len_conv = unit_to_user("length", "angstrom", 1)
        self.energy_conv = unit_to_user("energy", "electronvolt", 1)
        self.force_conv = unit_to_user("force", "ev/ang", 1)
Beispiel #5
0
    def store(self, value, units=""):
        """Converts the data to the appropriate data type and units and stores it.

        Args:
           value: The raw data to be stored.
           units: Optional string giving the units that the data should be stored
              in.
        """

        super(InputValue, self).store(value)

        if units != "":
            self.units.store(units)  # User can define in the code the units to be printed

        self.value = value
        if self._dimension != "undefined":
            self.value *= unit_to_user(self._dimension, units, 1.0)
Beispiel #6
0
    def write(self):
        """Outputs the required properties of the system.

        Note that properties are outputted using the same format as for the
        output to the xml checkpoint files, as specified in io_xml.

        Raises:
           KeyError: Raised if one of the properties specified in the output list
              are not contained in the property_dict member of properties.
        """

        if softexit.triggered: return  # don't write if we are about to exit!

        if not (self.system.simul.step + 1) % self.stride == 0:
            return
        self.out.write("  ")
        for what in self.outlist:
            try:
                quantity, dimension, unit = self.system.properties[what]
                if dimension != "" and unit != "":
                    quantity = unit_to_user(dimension, unit, quantity)
            except KeyError:
                raise KeyError(what + " is not a recognized property")
            if not hasattr(quantity, "__len__"):
                self.out.write(write_type(float, quantity) + "   ")
            else:
                for el in quantity:
                    self.out.write(write_type(float, el) + " ")

        self.out.write("\n")

        self.nout += 1
        if self.flush > 0 and self.nout >= self.flush:
            self.out.flush()
            os.fsync(self.out)  # we REALLY want to print out! pretty please OS let us do it.
            self.nout = 0
Beispiel #7
0
def totalEnergy(prefix, temp, ss=0):
    """
    Computes the virial centroid estimator for the total energy and PPI correction.
    """

    global temperature, skipSteps

    temperature = unit_to_internal("temperature", "kelvin", float(temp))
    skipSteps = int(ss)

    f2_av, ePA_av, eVir_av, f2ePA_av = 0.0, 0.0, 0.0, 0.0  # average square forces, virial and primitive energy
    # estimators, and the product of the primitive energy estimator and square forces

    ipos = []  # input positions files
    for filename in sorted(glob.glob(prefix + ".pos*")):
        ipos.append(open(filename, "r"))

    ifor = []  # input forces files
    for filename in sorted(glob.glob(prefix + ".for*")):
        ifor.append(open(filename, "r"))

    iU = None  # input potential energy and simulation time file
    for filename in sorted(glob.glob(prefix + ".out")):
        iU = open(filename, "r")

    global potentialEnergyUnit, timeUnit
    timeUnit, potentialEnergyUnit = extractUnits(iU)  # extracting simulation time and potential energy units

    iE = open(prefix + ".energy" + ".dat", "w")
    iE.write("# Simulation time (in %s), virial total energy and PPI energy correction (in %s)\n" %
             (timeUnit, potentialEnergyUnit))

    nbeads = len(ipos)
    if (nbeads != len(ifor)): raise ValueError("Mismatch between number of output files for forces and positions")
    natoms = 0
    ifr = 0
    time0 = 0
    q, f, m = None, None, None
    while True:  # Reading input files and calculating PPI correction
        try:
            for i in range(nbeads):
                ret = read_file("xyz", ipos[i])
                m, n = ret["masses"], ret["atoms"].natoms
                pos = unit_to_internal(ret["units"][0], ret["units"][1], ret["atoms"].q)
                ret = read_file("xyz", ifor[i])
                force = unit_to_internal(ret["units"][0], ret["units"][1], ret["atoms"].q)
                if natoms == 0:
                    natoms = n
                    q = np.zeros((nbeads, 3 * natoms))
                    f = np.zeros((nbeads, 3 * natoms))
                q[i, :] = pos
                f[i, :] = force
            time, U = read_U(iU)
        except EOFError:  # finished reading files
            sys.exit(0)

        if ifr < skipSteps:
            time0 = time

        if ifr >= skipSteps:  # PPI correction
            time -= time0

            ePA, f2, f2ePA = 0.0, 0.0, 0.0
            eVir, rc = 0.0, np.zeros(3)

            for j in range(nbeads):
                for i in range(natoms):
                    f2 += np.dot(f[j, i * 3:i * 3 + 3], f[j, i * 3:i * 3 + 3]) / m[i]
            for i in range(natoms):
                ePA -= np.dot(q[0, i * 3:i * 3 + 3] - q[nbeads - 1, i * 3:i * 3 + 3], q[0, i * 3:i * 3 + 3] - q[nbeads - 1, i * 3:i * 3 + 3]) * m[i]
            for j in range(nbeads - 1):
                for i in range(natoms):
                    ePA -= np.dot(q[j + 1, i * 3:i * 3 + 3] - q[j, i * 3:i * 3 + 3], q[j + 1, i * 3:i * 3 + 3] - q[j, i * 3:i * 3 + 3]) * m[i]
            for i in range(natoms):
                rc[:] = 0.0
                for j in range(nbeads):
                    rc[:] += q[j, i * 3:i * 3 + 3]
                rc[:] /= nbeads
                for j in range(nbeads):
                    eVir += np.dot(rc[:] - q[j, i * 3:i * 3 + 3], f[j, i * 3:i * 3 + 3])

            ePA *= 0.5 * nbeads * (Constants.kb * temperature)**2 / Constants.hbar**2
            ePA += 0.5 * nbeads * (3 * natoms) * Constants.kb * temperature + U
            f2ePA = f2 * ePA
            eVir /= 2.0 * nbeads
            eVir += 0.5 * (3 * natoms) * Constants.kb * temperature + U

            ePA_av += ePA
            f2_av += f2
            f2ePA_av += f2ePA
            eVir_av += eVir
            ifr += 1
            print(ifr - skipSteps)  # Printing current time frame (excluding thermalization)

            dE = (3.0 * Constants.kb * temperature + ePA_av / float(ifr - skipSteps)) * f2_av / float(ifr - skipSteps) - \
                f2ePA_av / float(ifr - skipSteps)
            dE *= Constants.hbar**2 / (24.0 * (nbeads * Constants.kb * temperature)**3)

            dE = unit_to_user("energy", potentialEnergyUnit, dE)  # Output in the same unit as potential energy
            eVir = unit_to_user("energy", potentialEnergyUnit, eVir_av / float(ifr - skipSteps))  # Output in the same unit
            # as potential energy

            iE.write("%f    %f     %f\n" % (time, eVir, dE))

        else:
            ifr += 1
def potentialEnergy(prefix, temp, ss=0, unit=''):
    """
    Computes the estimator for the potential energy and PPI correction.
    """

    # Adding fortran functions (when exist)
    sys.path.append(os.path.abspath(os.path.dirname(sys.argv[0]))[:-2] + 'f90')
    fast_code = True
    try:
        import fortran
    except:
        fast_code = False
        print('WARNING: No compiled fortran module for fast calculations have been found.\n'
              'Calculations will use a slower python script.')

    temperature = unit_to_internal("temperature", "kelvin", float(temp))  # simulation temperature
    skipSteps = int(ss)                                                  # steps to skip for thermalization

    f2_av, U_av, f2U_av = 0.0, 0.0, 0.0  # some required sums

    fns_for = sorted(glob.glob(prefix + ".for*"))
    fns_iU = glob.glob(prefix + ".out")[0]
    fn_out_en = prefix + ".potential_energy.dat"

    # Extracting the number of beads
    nbeads = len(fns_for)

    # print some information
    print 'temperature = {:f} K'.format(float(temp))
    print
    print 'number of beads = {:d}'.format(nbeads)
    print
    print 'forces file names:'
    for fn_for in fns_for:
        print '{:s}'.format(fn_for)
    print
    print 'potential energy file: {:s}'.format(fns_iU)
    print
    print 'output file name:'
    print fn_out_en
    print

    # open input and output files
    ifor = [open(fn, "r") for fn in fns_for]
    iU = open(fns_iU, "r")
    iE = open(fn_out_en, "w")

    # Some constants
    beta = 1.0 / (Constants.kb * temperature)
    const = Constants.hbar**2 * beta**2 / (24.0 * nbeads**3)

    timeUnit, potentialEnergyUnit, potentialEnergy_index, time_index = extractUnits(iU)  # extracting simulation time
    # and potential energy units

    # Defining the output energy unit
    if unit == '':
        unit = potentialEnergyUnit

    iE.write("# Simulation time (in %s), potential energy and PPI potential energy corrections (in %s)\n" %
             (timeUnit, unit))

    natoms = 0
    ifr = 0
    time0 = 0
    f, m = None, None
    while True:  # Reading input files and calculating PPI correction

        if ifr % 100 == 0:
            print '\rProcessing frame {:d}'.format(ifr),
            sys.stdout.flush()

        try:
            for i in range(nbeads):
                ret = read_file("xyz", ifor[i], output='arrays')
                if natoms == 0:
                    m, natoms = ret["masses"], ret["natoms"]
                    f = np.zeros((nbeads, 3 * natoms))
                f[i, :] = ret["data"]
            U, time = read_U(iU, potentialEnergyUnit, potentialEnergy_index, time_index)
        except EOFError:  # finished reading files
            sys.exit(0)

        if ifr < skipSteps:

            time0 = time

        if ifr >= skipSteps:  # PPI correction

            time -= time0

            f2 = 0.0

            if not fast_code:

                for j in range(nbeads):
                    for i in range(natoms):
                        f2 += np.dot(f[j, i * 3:i * 3 + 3], f[j, i * 3:i * 3 + 3]) / m[i]

            else:
                f2 = fortran.f2divm(np.array(f, order='F'), np.array(m, order='F'), natoms, nbeads)

            U_av += U
            f2_av += f2
            f2U_av += f2 * U
            ifr += 1

            norm = float(ifr - skipSteps)

            dU = 2.0 * f2_av / norm - beta * (f2U_av / norm - f2_av * U_av / norm**2)
            dU *= const

            dU = unit_to_user("energy", unit, dU)
            U = unit_to_user("energy", unit, U_av / float(ifr - skipSteps))

            iE.write("%f    %f     %f\n" % (time, U, dU))

        else:
            ifr += 1
def totalEnergy(prefix, temp, ss=0, unit=''):
    """
    Computes the virial centroid estimator for the total energy and PPI correction.
    """

    # Adding fortran functions (when exist)
    sys.path.append(os.path.abspath(os.path.dirname(sys.argv[0]))[:-2] + 'f90')
    fast_code = True
    try:
        import fortran
    except:
        fast_code = False
        print('WARNING: No compiled fortran module for fast calculations have been found.\n'
              'Calculations will use a slower python script.')

    temperature = unit_to_internal("temperature", "kelvin", float(temp))  # simulation temperature
    skipSteps = int(ss)                                                  # steps to skip for thermalization

    f2_av, ePA_av, eVir_av, f2ePA_av = 0.0, 0.0, 0.0, 0.0  # some required sums

    fns_pos = sorted(glob.glob(prefix + ".pos*"))
    fns_for = sorted(glob.glob(prefix + ".for*"))
    fns_iU = glob.glob(prefix + ".out")[0]
    fn_out_en = prefix + ".total_energy.dat"

    # check that we found the same number of positions and forces files
    nbeads = len(fns_pos)
    if nbeads != len(fns_for):
        print fns_pos
        print fns_for
        raise ValueError("Mismatch between number of input files for forces and positions.")

    # print some information
    print 'temperature = {:f} K'.format(float(temp))
    print
    print 'number of beads = {:d}'.format(nbeads)
    print
    print 'positions and forces file names:'
    for fn_pos, fn_for in zip(fns_pos, fns_for):
        print '{:s}   {:s}'.format(fn_pos, fn_for)
    print
    print 'potential energy file: {:s}'.format(fns_iU)
    print
    print 'output file name:'
    print fn_out_en
    print

    # open input and output files
    ipos = [open(fn, "r") for fn in fns_pos]
    ifor = [open(fn, "r") for fn in fns_for]
    iU = open(fns_iU, "r")
    iE = open(fn_out_en, "w")

    # Some constants
    beta = 1.0 / (Constants.kb * temperature)
    const_1 = 0.5 * nbeads / (beta * Constants.hbar)**2
    const_2 = 1.5 * nbeads / beta
    const_3 = 1.5 / beta
    const_4 = Constants.kb**2 / Constants.hbar**2
    const_5 = Constants.hbar**2 * beta**3 / (24.0 * nbeads**3)

    timeUnit, potentialEnergyUnit, potentialEnergy_index, time_index = extractUnits(iU)  # extracting simulation time
    # and potential energy units

    # Defining the output energy unit
    if unit == '':
        unit = potentialEnergyUnit

    iE.write("# Simulation time (in %s), virial total energy and PPI energy correction (in %s)\n" %
             (timeUnit, unit))

    natoms = 0
    ifr = 0
    time0 = 0
    q, f, m = None, None, None
    while True:  # Reading input files and calculating PPI correction

        if ifr % 100 == 0:
            print '\rProcessing frame {:d}'.format(ifr),
            sys.stdout.flush()

        try:
            for i in range(nbeads):
                ret = read_file("xyz", ipos[i], output='arrays')
                if natoms == 0:
                    m, natoms = ret["masses"], ret["natoms"]
                    q = np.zeros((nbeads, 3 * natoms))
                    f = np.zeros((nbeads, 3 * natoms))
                q[i, :] = ret["data"]
                f[i, :] = read_file("xyz", ifor[i], output='arrays')["data"]
            U, time = read_U(iU, potentialEnergyUnit, potentialEnergy_index, time_index)
        except EOFError:  # finished reading files
            sys.exit(0)

        if ifr < skipSteps:

            time0 = time

        if ifr >= skipSteps:  # PPI correction

            time -= time0

            ePA, f2, f2ePA, eVir = 0.0, 0.0, 0.0, 0.0

            if not fast_code:

                for j in range(nbeads):
                    for i in range(natoms):
                        f2 += np.dot(f[j, i * 3:i * 3 + 3], f[j, i * 3:i * 3 + 3]) / m[i]
                for i in range(natoms):
                    ePA -= np.dot(q[0, i * 3:i * 3 + 3] - q[nbeads - 1, i * 3:i * 3 + 3], q[0, i * 3:i * 3 + 3] - q[nbeads - 1, i * 3:i * 3 + 3]) * m[i]
                for j in range(nbeads - 1):
                    for i in range(natoms):
                        ePA -= np.dot(q[j + 1, i * 3:i * 3 + 3] - q[j, i * 3:i * 3 + 3], q[j + 1, i * 3:i * 3 + 3] - q[j, i * 3:i * 3 + 3]) * m[i]
                rc = np.zeros(3)
                for i in range(natoms):
                    rc[:] = 0.0
                    for j in range(nbeads):
                        rc[:] += q[j, i * 3:i * 3 + 3]
                    rc[:] /= nbeads
                    for j in range(nbeads):
                        eVir += np.dot(rc[:] - q[j, i * 3:i * 3 + 3], f[j, i * 3:i * 3 + 3])

                ePA *= const_1
                ePA += const_2 * natoms + U
                f2ePA = f2 * ePA
                eVir /= 2.0 * nbeads
                eVir += const_3 * natoms + U

            else:
                f2 = fortran.f2divm(np.array(f, order='F'), np.array(m, order='F'), natoms, nbeads)
                ePA = fortran.findcoupling(np.array(q, order='F'), np.array(m, order='F'), temperature, natoms, nbeads)
                eVir = fortran.findcentroidvirialkineticenergy(np.array(f, order='F'), np.array(q, order='F'), natoms, nbeads)

                ePA *= const_4
                ePA += const_2 * natoms + U
                f2ePA = f2 * ePA
                eVir += const_3 * natoms + U

            ePA_av += ePA
            f2_av += f2
            f2ePA_av += f2ePA
            eVir_av += eVir
            ifr += 1

            norm = float(ifr - skipSteps)

            dE = (3.0 * Constants.kb * temperature + ePA_av / norm) * f2_av / norm - f2ePA_av / norm
            dE *= const_5

            dE = unit_to_user("energy", unit, dE)
            eVir = unit_to_user("energy", unit, eVir_av / norm)

            iE.write("%f    %f     %f\n" % (time, eVir, dE))

        else:
            ifr += 1
Beispiel #10
0
def RDF(prefix, temp, A, B, nbins, r_min, r_max, ss=0, unit='angstrom'):

    # Adding fortran functions (when exist)
    sys.path.append(os.path.abspath(os.path.dirname(sys.argv[0]))[:-2] + 'f90')
    try:
        import fortran
    except:
        print('WARNING: No compiled fortran module for fast calculations have been found.\n'
              'Proceeding the calculations is not possible.')
        sys.exit(0)

    temperature = unit_to_internal("temperature", "kelvin", float(temp))  # simulation temperature
    skipSteps = int(ss)                                                  # steps to skip
    nbins = int(nbins)

    fns_pos = sorted(glob.glob(prefix + ".pos*"))
    fns_for = sorted(glob.glob(prefix + ".for*"))
    fn_out_rdf, fn_out_rdf_q = prefix + '.' + A + B + ".rdf.dat", prefix + '.' + A + B + ".rdf-ppi.dat"

    # check that we found the same number of positions and forces files
    nbeads = len(fns_pos)
    if nbeads != len(fns_for):
        print(fns_pos)
        print(fns_for)
        raise ValueError("Mismatch between number of input files for forces and positions.")

    # print some information
    print('temperature = {:f} K'.format(float(temp)))
    print()
    print('number of beads = {:d}'.format(nbeads))
    print()
    print('positions and forces file names:')
    for fn_pos, fn_for in zip(fns_pos, fns_for):
        print('{:s}   {:s}'.format(fn_pos, fn_for))
    print()
    print('output file names:')
    print(fn_out_rdf)
    print(fn_out_rdf_q)
    print()

    # open input and output files
    ipos = [open(fn, "r") for fn in fns_pos]
    ifor = [open(fn, "r") for fn in fns_for]
    # iRDF, iRDFq = open(fn_out_rdf, "w"), open(fn_out_rdf_q, "w")

    # Species for RDF
    species = (A, B)
    speciesMass = np.array([Elements.mass(species[0]), Elements.mass(species[1])], order='F')

    r_min = unit_to_internal('length', unit, float(r_min))  # Minimal distance for RDF
    r_max = unit_to_internal('length', unit, float(r_max))  # Maximal distance for RDF
    dr = (r_max - r_min) / nbins  # RDF step
    rdf = np.array([[r_min + (0.5 + i) * dr, 0] for i in range(nbins)], order='F')   # conventional RDF

    # RDF auxiliary variables
    cell = None         # simulation cell matrix
    inverseCell = None  # inverse simulation sell matrix
    cellVolume = None   # simulation cell volume
    natomsA = 0  # the total number of A type particles in the system
    natomsB = 0  # the total number of B type particles in the system
    # Here A and B are the types of elements used for RDF calculations

    # temp variables
    f2 = 0.0  # the sum of square forces divided by corresponding masses (f2/m)
    f2rdf = np.zeros(nbins, order='F')  # the sum f2/m multiplied by the rdf at each time step
    frdf = np.zeros(nbins, order='F')  # the sum of f/m multiplied by the rdf derivative at each time step

    natoms = 0  # total number of atoms
    ifr = 0     # time frame number
    pos, force, mass = None, None, None  # positions, forces, and mass arrays
    noteof = True  # end of file test variable

    while noteof:  # Reading input files and calculating PPI correction

        if ifr % 100 == 0:
            print('\rProcessing frame {:d}'.format(ifr), end=' ')
            sys.stdout.flush()

        try:
            for i in range(nbeads):
                ret = read_file("xyz", ipos[i], dimension='length')
                if natoms == 0:
                    mass, natoms = ret["atoms"].m, ret["atoms"].natoms
                    pos = np.zeros((nbeads, 3 * natoms), order='F')
                    force = np.zeros((nbeads, 3 * natoms), order='F')
                cell = ret["cell"].h
                inverseCell = ret["cell"].get_ih()
                cellVolume = ret["cell"].get_volume()
                pos[i, :] = ret["atoms"].q
                force[i, :] = read_file("xyz", ifor[i], dimension='force')["atoms"].q
        except EOFError:  # finished reading files
            noteof = False

        if noteof:
            if ifr >= skipSteps:  # RDF calculations

                species_A = [3 * i + j for i in np.where(mass == speciesMass[0])[0] for j in range(3)]
                species_B = [3 * i + j for i in np.where(mass == speciesMass[1])[0] for j in range(3)]
                natomsA = len(species_A)
                natomsB = len(species_B)
                posA = np.zeros((nbeads, natomsA), order='F')
                posB = np.zeros((nbeads, natomsB), order='F')
                forA = np.zeros((nbeads, natomsA), order='F')
                forB = np.zeros((nbeads, natomsB), order='F')
                for bead in range(nbeads):
                    posA[bead, :] = pos[bead, species_A]
                    forA[bead, :] = force[bead, species_A]
                    posB[bead, :] = pos[bead, species_B]
                    forB[bead, :] = force[bead, species_B]

                # RDF amd PPI RDF calculations
                f2temp = fortran.f2divm(force, mass, natoms, nbeads)
                f2 += f2temp
                fortran.updateqrdf(rdf, f2rdf, frdf, posA, posB, forA, forB, natomsA / 3, natomsB / 3, nbins, r_min, r_max, cell,
                                   inverseCell, nbeads, f2temp, speciesMass[0], speciesMass[1])

                ifr += 1

            else:
                ifr += 1

            if ifr > skipSteps and ifr % 100 == 0:

                # Some constants
                const = 1.0 / float(ifr - skipSteps)
                alpha = Constants.hbar**2 / (24.0 * nbeads**3 * (temperature * Constants.kb)**3)
                beta = Constants.hbar**2 / (12.0 * nbeads**3 * (temperature * Constants.kb)**2)

                # Normalization
                _rdf = np.copy(rdf)
                _f2rdf = np.copy(f2rdf)
                _frdf = np.copy(frdf)
                _rdf[:, 1] *= const / nbeads
                _f2 = f2 * alpha * const
                _f2rdf[:] *= alpha * const
                _frdf[:] *= beta * const

                # PPI correction
                rdfQ = np.copy(_rdf)
                for bin in range(nbins):
                    rdfQ[bin, 1] += (_rdf[bin, 1] * _f2 - _f2rdf[bin] / nbeads)
                    rdfQ[bin, 1] -= _frdf[bin] / 2.0

                # Creating RDF from N(r)
                const, dr = cellVolume / (4 * np.pi / 3.0), _rdf[1, 0] - _rdf[0, 0]
                for bin in range(nbins):
                    _rdf[bin, 1] = const * _rdf[bin, 1] / ((_rdf[bin, 0] + 0.5 * dr)**3 - (_rdf[bin, 0] - 0.5 * dr)**3)
                    rdfQ[bin, 1] = const * rdfQ[bin, 1] / ((rdfQ[bin, 0] + 0.5 * dr)**3 - (rdfQ[bin, 0] - 0.5 * dr)**3)
                for bin in range(nbins):
                    _rdf[bin, 0] = unit_to_user('length', unit, _rdf[bin, 0])
                    rdfQ[bin, 0] = unit_to_user('length', unit, rdfQ[bin, 0])

                # Writing the results into files
                np.savetxt(fn_out_rdf, _rdf)
                np.savetxt(fn_out_rdf_q, rdfQ)
Beispiel #11
0
def energies(prefix, temp, ss=0, unit=''):
    """
    Computes the virial centroid estimator for the total energy and PPI correction.
    """

    # Adding fortran functions (when exist)
    sys.path.append(os.path.abspath(os.path.dirname(sys.argv[0]))[:-2] + 'f90')
    fast_code = True
    try:
        import fortran
    except:
        fast_code = False
        print('WARNING: No compiled fortran module for fast calculations have been found.\n'
              'Calculations will use a slower python script.')

    temperature = unit_to_internal("temperature", "kelvin", float(temp))  # simulation temperature
    skipSteps = int(ss)                                                  # steps to skip for thermalization

    KPa_av, KVir_av, U_av, f2_av, f2KPa_av, f2U_av = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  # some required sums

    fns_pos = sorted(glob.glob(prefix + ".pos*"))
    fns_for = sorted(glob.glob(prefix + ".for*"))
    fns_iU = glob.glob(prefix + ".out")[0]
    fn_out_en = prefix + ".energies.dat"

    # check that we found the same number of positions and forces files
    nbeads = len(fns_pos)
    if nbeads != len(fns_for):
        print fns_pos
        print fns_for
        raise ValueError("Mismatch between number of input files for forces and positions.")

    # print some information
    print 'temperature = {:f} K'.format(float(temp))
    print
    print 'number of beads = {:d}'.format(nbeads)
    print
    print 'positions and forces file names:'
    for fn_pos, fn_for in zip(fns_pos, fns_for):
        print '{:s}   {:s}'.format(fn_pos, fn_for)
    print
    print 'potential energy file: {:s}'.format(fns_iU)
    print
    print 'output file name:'
    print fn_out_en
    print

    # open input and output files
    ipos = [open(fn, "r") for fn in fns_pos]
    ifor = [open(fn, "r") for fn in fns_for]
    iU = open(fns_iU, "r")
    iE = open(fn_out_en, "w")

    # Some constants
    beta = 1.0 / (Constants.kb * temperature)
    const_1 = 0.5 * nbeads / (beta * Constants.hbar)**2
    const_2 = 1.5 * nbeads / beta
    const_3 = 1.5 / beta
    const_4 = Constants.kb**2 / Constants.hbar**2
    const_5 = Constants.hbar**2 * beta**3 / (24.0 * nbeads**3)
    const_6 = Constants.hbar**2 * beta**2 / (24.0 * nbeads**3)

    timeUnit, potentialEnergyUnit, potentialEnergy_index, time_index = extractUnits(iU)  # extracting simulation time
    # and potential energy units

    # Defining the output energy unit
    if unit == '':
        unit = potentialEnergyUnit

    iE.write("# Simulation time (in %s), improved total energy estimator, virial total energy estimator, and PPI "
             "correction for the total energy; improved potential energy estimator, potential energy estimatorand, "
             "PPI correction for the potential energy; improved kinetic energy estimator, virial kinetic energy "
             "estimator, and PPI correction for the kinetic energy (all in %s)\n" % (timeUnit, unit))
    iE.close()

    natoms = 0
    ifr = 0
    time0 = 0
    q, f, m = None, None, None
    while True:  # Reading input files and calculating PPI correction

        if ifr % 100 == 0:
            print '\rProcessing frame {:d}'.format(ifr),
            sys.stdout.flush()

        try:
            for i in range(nbeads):
                ret = read_file("xyz", ipos[i], dimension='length')["atoms"]
                if natoms == 0:
                    m, natoms = ret.m, ret.natoms
                    q = np.zeros((nbeads, 3 * natoms))
                    f = np.zeros((nbeads, 3 * natoms))
                q[i, :] = ret.q
                f[i, :] = read_file("xyz", ifor[i], dimension='force')["atoms"].q
            U, time = read_U(iU, potentialEnergyUnit, potentialEnergy_index, time_index)
        except EOFError:  # finished reading files
            sys.exit(0)

        if ifr < skipSteps:

            time0 = time

        if ifr >= skipSteps:  # PPI correction

            time -= time0

            KPa, f2, KVir = 0.0, 0.0, 0.0

            if not fast_code:

                for j in range(nbeads):
                    for i in range(natoms):
                        f2 += np.dot(f[j, i * 3:i * 3 + 3], f[j, i * 3:i * 3 + 3]) / m[i]
                for i in range(natoms):
                    KPa -= np.dot(q[0, i * 3:i * 3 + 3] - q[nbeads - 1, i * 3:i * 3 + 3], q[0, i * 3:i * 3 + 3] - q[nbeads - 1, i * 3:i * 3 + 3]) * m[i]
                for j in range(nbeads - 1):
                    for i in range(natoms):
                        KPa -= np.dot(q[j + 1, i * 3:i * 3 + 3] - q[j, i * 3:i * 3 + 3], q[j + 1, i * 3:i * 3 + 3] - q[j, i * 3:i * 3 + 3]) * m[i]
                rc = np.zeros(3)
                for i in range(natoms):
                    rc[:] = 0.0
                    for j in range(nbeads):
                        rc[:] += q[j, i * 3:i * 3 + 3]
                    rc[:] /= nbeads
                    for j in range(nbeads):
                        KVir += np.dot(rc[:] - q[j, i * 3:i * 3 + 3], f[j, i * 3:i * 3 + 3])

                KPa *= const_1
                KPa += const_2 * natoms
                KVir /= 2.0 * nbeads
                KVir += const_3 * natoms

            else:

                f2 = fortran.f2divm(np.array(f, order='F'), np.array(m, order='F'), natoms, nbeads)
                KPa = fortran.findcoupling(np.array(q, order='F'), np.array(m, order='F'), temperature, natoms, nbeads)
                KVir = fortran.findcentroidvirialkineticenergy(np.array(f, order='F'), np.array(q, order='F'), natoms, nbeads)

                KPa *= const_4
                KPa += const_2 * natoms
                KVir += const_3 * natoms

            f2_av += f2
            KPa_av += KPa
            f2KPa_av += f2 * KPa
            U_av += U
            f2U_av += f2 * U
            KVir_av += KVir
            ifr += 1

            norm = float(ifr - skipSteps)

            dU = 2 * f2_av / norm - beta * (f2U_av / norm - f2_av * U_av / norm**2)
            dU *= const_6
            dU = unit_to_user("energy", unit, dU)

            dK = (Constants.kb * temperature + KPa_av / norm) * f2_av / norm - f2KPa_av / norm
            dK *= const_5
            dK = unit_to_user("energy", unit, dK)

            U = unit_to_user("energy", unit, U_av / norm)
            KVir = unit_to_user("energy", unit, KVir_av / norm)

            iE = open(fn_out_en, "a")
            iE.write("%f    %f     %f     %f     %f    %f     %f     %f     %f     %f\n"
                     % (time, KVir + U + dK + dU, KVir + U, dK + dU, U + dU, U, dU, KVir + dK, KVir, dK))
            iE.close()

        else:
            ifr += 1
Beispiel #12
0
    def step(self, step=None):
        """ Does one simulation time step."""

        activearrays = self.pre_step(step)

        fff = activearrays["old_f"] * (self.im.coef[1:] + self.im.coef[:-1]) / 2
        f = (fff + self.im.f).reshape(self.im.dbeads.natoms * 3 * self.im.dbeads.nbeads, 1)

        banded = False
        banded = True
        if banded:
            # BANDED Version
            # MASS-scaled
            dyn_mat = get_dynmat(activearrays["hessian"], self.im.dbeads.m3, self.im.dbeads.nbeads)
            h_up_band = banded_hessian(dyn_mat, self.im, masses=False, shift=0.000000001)  # create upper band matrix
            f = np.multiply(f, self.im.dbeads.m3.reshape(f.shape)**-0.5)
            # CARTESIAN
            # h_up_band = banded_hessian(activearrays["hessian"], self.im,masses=True)  # create upper band matrix

            d = diag_banded(h_up_band)
        else:
            # FULL dimensions version
            h_0 = red2comp(activearrays["hessian"], self.im.dbeads.nbeads, self.im.dbeads.natoms, self.im.coef)
            h_test = np.add(self.im.h, h_0)  # add spring terms to the physical hessian
            d, w = clean_hessian(h_test, self.im.dbeads.q, self.im.dbeads.natoms,
                                 self.im.dbeads.nbeads, self.im.dbeads.m, self.im.dbeads.m3, None)
            # CARTESIAN
            # d,w =np.linalg.eigh(h_test) #Cartesian
        info('\n@Lanczos: 1st freq {} cm^-1'.format(units.unit_to_user('frequency', 'inversecm', np.sign(d[0]) * np.sqrt(np.absolute(d[0])))), verbosity.medium)
        info('@Lanczos: 2nd freq {} cm^-1'.format(units.unit_to_user('frequency', 'inversecm', np.sign(d[1]) * np.sqrt(np.absolute(d[1])))), verbosity.medium)
        info('@Lanczos: 3rd freq {} cm^-1\n'.format(units.unit_to_user('frequency', 'inversecm', np.sign(d[2]) * np.sqrt(np.absolute(d[2])))), verbosity.medium)

        if d[0] > 0:
            if d[1] / 2 > d[0]:
                alpha = 1
                lamb = (2 * d[0] + d[1]) / 4
            else:
                alpha = (d[1] - d[0]) / d[1]
                lamb = (3 * d[0] + d[1]) / 4  # midpoint between b[0] and b[1]*(1-alpha/2)
        elif d[1] < 0:  # Jeremy Richardson
            if (d[1] >= d[0] / 2):
                alpha = 1
                lamb = (d[0] + 2 * d[1]) / 4
            else:
                alpha = (d[0] - d[1]) / d[1]
                lamb = (d[0] + 3 * d[1]) / 4
        # elif d[1] < 0:  #Litman for Second Order Saddle point
        #    alpha = 1
        #    lamb = (d[1] + d[2]) / 4
        #    print 'WARNING: We are not using the standard Nichols'
        #    print 'd_x', d_x[0],d_x[1]

        else:  # Only d[0] <0
            alpha = 1
            lamb = (d[0] + d[1]) / 4

        if banded:
            h_up_band[-1, :] += - np.ones(h_up_band.shape[1]) * lamb
            d_x = invmul_banded(h_up_band, f)
        else:
            h_test = alpha * (h_test - np.eye(h_test.shape[0]) * lamb)
            d_x = np.linalg.solve(h_test, f)

        d_x.shape = self.im.dbeads.q.shape

        # MASS-scaled
        d_x = np.multiply(d_x, self.im.dbeads.m3**-0.5)

        # Rescale step if necessary
        if np.amax(np.absolute(d_x)) > activearrays["big_step"]:
            info("Step norm, scaled down to {}".format(activearrays["big_step"]), verbosity.low)
            d_x *= activearrays["big_step"] / np.amax(np.absolute(d_x))

        # Get the new full-position
        d_x_full = self.fix.get_full_vector(d_x, t=1)
        new_x = self.optarrays["old_x"].copy() + d_x_full

        self.post_step(step, new_x, d_x, activearrays)
Beispiel #13
0
def totalEnergy(prefix, temp, ss=0, unit=''):
    """
    Computes the virial centroid estimator for the total energy and PPI correction.
    """

    # Adding fortran functions (when exist)
    sys.path.append(os.path.abspath(os.path.dirname(sys.argv[0]))[:-2] + 'f90')
    fast_code = True
    try:
        import fortran
    except:
        fast_code = False
        print(
            'WARNING: No compiled fortran module for fast calculations have been found.\n'
            'Calculations will use a slower python script.')

    temperature = unit_to_internal("temperature", "kelvin",
                                   float(temp))  # simulation temperature
    skipSteps = int(ss)  # steps to skip for thermalization

    f2_av, ePA_av, eVir_av, f2ePA_av = 0.0, 0.0, 0.0, 0.0  # some required sums

    fns_pos = sorted(glob.glob(prefix + ".pos*"))
    fns_for = sorted(glob.glob(prefix + ".for*"))
    fns_iU = glob.glob(prefix + ".out")[0]
    fn_out_en = prefix + ".total_energy.dat"

    # check that we found the same number of positions and forces files
    nbeads = len(fns_pos)
    if nbeads != len(fns_for):
        print fns_pos
        print fns_for
        raise ValueError(
            "Mismatch between number of input files for forces and positions.")

    # print some information
    print 'temperature = {:f} K'.format(float(temp))
    print
    print 'number of beads = {:d}'.format(nbeads)
    print
    print 'positions and forces file names:'
    for fn_pos, fn_for in zip(fns_pos, fns_for):
        print '{:s}   {:s}'.format(fn_pos, fn_for)
    print
    print 'potential energy file: {:s}'.format(fns_iU)
    print
    print 'output file name:'
    print fn_out_en
    print

    # open input and output files
    ipos = [open(fn, "r") for fn in fns_pos]
    ifor = [open(fn, "r") for fn in fns_for]
    iU = open(fns_iU, "r")
    iE = open(fn_out_en, "w")

    # Some constants
    beta = 1.0 / (Constants.kb * temperature)
    const_1 = 0.5 * nbeads / (beta * Constants.hbar)**2
    const_2 = 1.5 * nbeads / beta
    const_3 = 1.5 / beta
    const_4 = Constants.kb**2 / Constants.hbar**2
    const_5 = Constants.hbar**2 * beta**3 / (24.0 * nbeads**3)

    timeUnit, potentialEnergyUnit, potentialEnergy_index, time_index = extractUnits(
        iU)  # extracting simulation time
    # and potential energy units

    # Defining the output energy unit
    if unit == '':
        unit = potentialEnergyUnit

    iE.write(
        "# Simulation time (in %s), virial total energy and PPI energy correction (in %s)\n"
        % (timeUnit, unit))

    natoms = 0
    ifr = 0
    time0 = 0
    q, f, m = None, None, None
    while True:  # Reading input files and calculating PPI correction

        if ifr % 100 == 0:
            print '\rProcessing frame {:d}'.format(ifr),
            sys.stdout.flush()

        try:
            for i in range(nbeads):
                ret = read_file("xyz", ipos[i], output='arrays')
                if natoms == 0:
                    m, natoms = ret["masses"], ret["natoms"]
                    q = np.zeros((nbeads, 3 * natoms))
                    f = np.zeros((nbeads, 3 * natoms))
                q[i, :] = ret["data"]
                f[i, :] = read_file("xyz", ifor[i], output='arrays')["data"]
            U, time = read_U(iU, potentialEnergyUnit, potentialEnergy_index,
                             time_index)
        except EOFError:  # finished reading files
            sys.exit(0)

        if ifr < skipSteps:

            time0 = time

        if ifr >= skipSteps:  # PPI correction

            time -= time0

            ePA, f2, f2ePA, eVir = 0.0, 0.0, 0.0, 0.0

            if not fast_code:

                for j in range(nbeads):
                    for i in range(natoms):
                        f2 += np.dot(f[j, i * 3:i * 3 + 3],
                                     f[j, i * 3:i * 3 + 3]) / m[i]
                for i in range(natoms):
                    ePA -= np.dot(
                        q[0, i * 3:i * 3 + 3] - q[nbeads - 1, i * 3:i * 3 + 3],
                        q[0, i * 3:i * 3 + 3] -
                        q[nbeads - 1, i * 3:i * 3 + 3]) * m[i]
                for j in range(nbeads - 1):
                    for i in range(natoms):
                        ePA -= np.dot(
                            q[j + 1, i * 3:i * 3 + 3] - q[j, i * 3:i * 3 + 3],
                            q[j + 1, i * 3:i * 3 + 3] -
                            q[j, i * 3:i * 3 + 3]) * m[i]
                rc = np.zeros(3)
                for i in range(natoms):
                    rc[:] = 0.0
                    for j in range(nbeads):
                        rc[:] += q[j, i * 3:i * 3 + 3]
                    rc[:] /= nbeads
                    for j in range(nbeads):
                        eVir += np.dot(rc[:] - q[j, i * 3:i * 3 + 3],
                                       f[j, i * 3:i * 3 + 3])

                ePA *= const_1
                ePA += const_2 * natoms + U
                f2ePA = f2 * ePA
                eVir /= 2.0 * nbeads
                eVir += const_3 * natoms + U

            else:
                f2 = fortran.f2divm(np.array(f, order='F'),
                                    np.array(m, order='F'), natoms, nbeads)
                ePA = fortran.findcoupling(np.array(q, order='F'),
                                           np.array(m, order='F'), temperature,
                                           natoms, nbeads)
                eVir = fortran.findcentroidvirialkineticenergy(
                    np.array(f, order='F'), np.array(q, order='F'), natoms,
                    nbeads)

                ePA *= const_4
                ePA += const_2 * natoms + U
                f2ePA = f2 * ePA
                eVir += const_3 * natoms + U

            ePA_av += ePA
            f2_av += f2
            f2ePA_av += f2ePA
            eVir_av += eVir
            ifr += 1

            norm = float(ifr - skipSteps)

            dE = (3.0 * Constants.kb * temperature +
                  ePA_av / norm) * f2_av / norm - f2ePA_av / norm
            dE *= const_5

            dE = unit_to_user("energy", unit, dE)
            eVir = unit_to_user("energy", unit, eVir_av / norm)

            iE.write("%f    %f     %f\n" % (time, eVir, dE))

        else:
            ifr += 1
Beispiel #14
0
def totalEnergy(prefix, temp, ss=0):
    """
    Computes the virial centroid estimator for the total energy and PPI correction.
    """

    global temperature, skipSteps

    temperature = unit_to_internal("temperature", "kelvin", float(temp))
    skipSteps = int(ss)

    f2_av, ePA_av, eVir_av, f2ePA_av = (
        0.0,
        0.0,
        0.0,
        0.0,
    )  # average square forces, virial and primitive energy
    # estimators, and the product of the primitive energy estimator and square forces

    ipos = []  # input positions files
    for filename in sorted(glob.glob(prefix + ".pos*")):
        ipos.append(open(filename, "r"))

    ifor = []  # input forces files
    for filename in sorted(glob.glob(prefix + ".for*")):
        ifor.append(open(filename, "r"))

    iU = None  # input potential energy and simulation time file
    for filename in sorted(glob.glob(prefix + ".out")):
        iU = open(filename, "r")

    global potentialEnergyUnit, timeUnit
    timeUnit, potentialEnergyUnit = extractUnits(
        iU
    )  # extracting simulation time and potential energy units

    iE = open(prefix + ".energy" + ".dat", "w")
    iE.write(
        "# Simulation time (in %s), virial total energy and PPI energy correction (in %s)\n"
        % (timeUnit, potentialEnergyUnit)
    )

    nbeads = len(ipos)
    if nbeads != len(ifor):
        raise ValueError(
            "Mismatch between number of output files for forces and positions"
        )
    natoms = 0
    ifr = 0
    time0 = 0
    q, f, m = None, None, None
    while True:  # Reading input files and calculating PPI correction
        try:
            for i in range(nbeads):
                ret = read_file("xyz", ipos[i])
                m, n = ret["masses"], ret["atoms"].natoms
                pos = unit_to_internal(ret["units"][0], ret["units"][1], ret["atoms"].q)
                ret = read_file("xyz", ifor[i])
                force = unit_to_internal(
                    ret["units"][0], ret["units"][1], ret["atoms"].q
                )
                if natoms == 0:
                    natoms = n
                    q = np.zeros((nbeads, 3 * natoms))
                    f = np.zeros((nbeads, 3 * natoms))
                q[i, :] = pos
                f[i, :] = force
            time, U = read_U(iU)
        except EOFError:  # finished reading files
            sys.exit(0)

        if ifr < skipSteps:
            time0 = time

        if ifr >= skipSteps:  # PPI correction
            time -= time0

            ePA, f2, f2ePA = 0.0, 0.0, 0.0
            eVir, rc = 0.0, np.zeros(3)

            for j in range(nbeads):
                for i in range(natoms):
                    f2 += (
                        np.dot(f[j, i * 3 : i * 3 + 3], f[j, i * 3 : i * 3 + 3]) / m[i]
                    )
            for i in range(natoms):
                ePA -= (
                    np.dot(
                        q[0, i * 3 : i * 3 + 3] - q[nbeads - 1, i * 3 : i * 3 + 3],
                        q[0, i * 3 : i * 3 + 3] - q[nbeads - 1, i * 3 : i * 3 + 3],
                    )
                    * m[i]
                )
            for j in range(nbeads - 1):
                for i in range(natoms):
                    ePA -= (
                        np.dot(
                            q[j + 1, i * 3 : i * 3 + 3] - q[j, i * 3 : i * 3 + 3],
                            q[j + 1, i * 3 : i * 3 + 3] - q[j, i * 3 : i * 3 + 3],
                        )
                        * m[i]
                    )
            for i in range(natoms):
                rc[:] = 0.0
                for j in range(nbeads):
                    rc[:] += q[j, i * 3 : i * 3 + 3]
                rc[:] /= nbeads
                for j in range(nbeads):
                    eVir += np.dot(
                        rc[:] - q[j, i * 3 : i * 3 + 3], f[j, i * 3 : i * 3 + 3]
                    )

            ePA *= (
                0.5 * nbeads * (Constants.kb * temperature) ** 2 / Constants.hbar ** 2
            )
            ePA += 0.5 * nbeads * (3 * natoms) * Constants.kb * temperature + U
            f2ePA = f2 * ePA
            eVir /= 2.0 * nbeads
            eVir += 0.5 * (3 * natoms) * Constants.kb * temperature + U

            ePA_av += ePA
            f2_av += f2
            f2ePA_av += f2ePA
            eVir_av += eVir
            ifr += 1
            print(
                (ifr - skipSteps)
            )  # Printing current time frame (excluding thermalization)

            dE = (
                3.0 * Constants.kb * temperature + ePA_av / float(ifr - skipSteps)
            ) * f2_av / float(ifr - skipSteps) - f2ePA_av / float(ifr - skipSteps)
            dE *= Constants.hbar ** 2 / (
                24.0 * (nbeads * Constants.kb * temperature) ** 3
            )

            dE = unit_to_user(
                "energy", potentialEnergyUnit, dE
            )  # Output in the same unit as potential energy
            eVir = unit_to_user(
                "energy", potentialEnergyUnit, eVir_av / float(ifr - skipSteps)
            )  # Output in the same unit
            # as potential energy

            iE.write("%f    %f     %f\n" % (time, eVir, dE))

        else:
            ifr += 1
Beispiel #15
0
def energies(prefix, temp, ss=0, unit=""):
    """
    Computes the virial centroid estimator for the total energy and PPI correction.
    """

    # Adding fortran functions (when exist)
    sys.path.append(os.path.abspath(os.path.dirname(sys.argv[0]))[:-2] + "f90")
    fast_code = True
    try:
        import fortran
    except ImportError:
        fast_code = False
        print(
            "WARNING: No compiled fortran module for fast calculations have been found.\n"
            "Calculations will use a slower python script.")

    temperature = unit_to_internal("temperature", "kelvin",
                                   float(temp))  # simulation temperature
    skipSteps = int(ss)  # steps to skip for thermalization

    KPa_av, KVir_av, U_av, f2_av, f2KPa_av, f2U_av = (
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
    )  # some required sums

    fns_pos = sorted(glob.glob(prefix + ".pos*"))
    fns_for = sorted(glob.glob(prefix + ".for*"))
    fns_iU = glob.glob(prefix + ".out")[0]
    fn_out_en = prefix + ".energies.dat"

    # check that we found the same number of positions and forces files
    nbeads = len(fns_pos)
    if nbeads != len(fns_for):
        print(fns_pos)
        print(fns_for)
        raise ValueError(
            "Mismatch between number of input files for forces and positions.")

    # print some information
    print("temperature = {:f} K".format(float(temp)))
    print()
    print("number of beads = {:d}".format(nbeads))
    print()
    print("positions and forces file names:")
    for fn_pos, fn_for in zip(fns_pos, fns_for):
        print("{:s}   {:s}".format(fn_pos, fn_for))
    print()
    print("potential energy file: {:s}".format(fns_iU))
    print()
    print("output file name:")
    print(fn_out_en)
    print()

    # open input and output files
    ipos = [open(fn, "r") for fn in fns_pos]
    ifor = [open(fn, "r") for fn in fns_for]
    iU = open(fns_iU, "r")
    iE = open(fn_out_en, "w")

    # Some constants
    beta = 1.0 / (Constants.kb * temperature)
    const_1 = 0.5 * nbeads / (beta * Constants.hbar)**2
    const_2 = 1.5 * nbeads / beta
    const_3 = 1.5 / beta
    const_4 = Constants.kb**2 / Constants.hbar**2
    const_5 = Constants.hbar**2 * beta**3 / (24.0 * nbeads**3)
    const_6 = Constants.hbar**2 * beta**2 / (24.0 * nbeads**3)

    timeUnit, potentialEnergyUnit, potentialEnergy_index, time_index = extractUnits(
        iU)  # extracting simulation time
    # and potential energy units

    # Defining the output energy unit
    if unit == "":
        unit = potentialEnergyUnit

    iE.write(
        "# Simulation time (in %s), improved total energy estimator, virial total energy estimator, and PPI "
        "correction for the total energy; improved potential energy estimator, potential energy estimatorand, "
        "PPI correction for the potential energy; improved kinetic energy estimator, virial kinetic energy "
        "estimator, and PPI correction for the kinetic energy (all in %s)\n" %
        (timeUnit, unit))
    iE.close()

    natoms = 0
    ifr = 0
    time0 = 0
    q, f, m = None, None, None
    while True:  # Reading input files and calculating PPI correction

        if ifr % 100 == 0:
            print("\rProcessing frame {:d}".format(ifr), end=" ")
            sys.stdout.flush()

        try:
            for i in range(nbeads):
                ret = read_file("xyz", ipos[i], dimension="length")["atoms"]
                if natoms == 0:
                    m, natoms = ret.m, ret.natoms
                    q = np.zeros((nbeads, 3 * natoms))
                    f = np.zeros((nbeads, 3 * natoms))
                q[i, :] = ret.q
                f[i, :] = read_file("xyz", ifor[i],
                                    dimension="force")["atoms"].q
            U, time = read_U(iU, potentialEnergyUnit, potentialEnergy_index,
                             time_index)
        except EOFError:  # finished reading files
            sys.exit(0)

        if ifr < skipSteps:

            time0 = time

        if ifr >= skipSteps:  # PPI correction

            time -= time0

            KPa, f2, KVir = 0.0, 0.0, 0.0

            if not fast_code:

                for j in range(nbeads):
                    for i in range(natoms):
                        f2 += (np.dot(f[j, i * 3:i * 3 + 3],
                                      f[j, i * 3:i * 3 + 3]) / m[i])
                for i in range(natoms):
                    KPa -= (np.dot(
                        q[0, i * 3:i * 3 + 3] - q[nbeads - 1, i * 3:i * 3 + 3],
                        q[0, i * 3:i * 3 + 3] - q[nbeads - 1, i * 3:i * 3 + 3],
                    ) * m[i])
                for j in range(nbeads - 1):
                    for i in range(natoms):
                        KPa -= (np.dot(
                            q[j + 1, i * 3:i * 3 + 3] - q[j, i * 3:i * 3 + 3],
                            q[j + 1, i * 3:i * 3 + 3] - q[j, i * 3:i * 3 + 3],
                        ) * m[i])
                rc = np.zeros(3)
                for i in range(natoms):
                    rc[:] = 0.0
                    for j in range(nbeads):
                        rc[:] += q[j, i * 3:i * 3 + 3]
                    rc[:] /= nbeads
                    for j in range(nbeads):
                        KVir += np.dot(rc[:] - q[j, i * 3:i * 3 + 3],
                                       f[j, i * 3:i * 3 + 3])

                KPa *= const_1
                KPa += const_2 * natoms
                KVir /= 2.0 * nbeads
                KVir += const_3 * natoms

            else:

                f2 = fortran.f2divm(np.array(f, order="F"),
                                    np.array(m, order="F"), natoms, nbeads)
                KPa = fortran.findcoupling(
                    np.array(q, order="F"),
                    np.array(m, order="F"),
                    temperature,
                    natoms,
                    nbeads,
                )
                KVir = fortran.findcentroidvirialkineticenergy(
                    np.array(f, order="F"), np.array(q, order="F"), natoms,
                    nbeads)

                KPa *= const_4
                KPa += const_2 * natoms
                KVir += const_3 * natoms

            f2_av += f2
            KPa_av += KPa
            f2KPa_av += f2 * KPa
            U_av += U
            f2U_av += f2 * U
            KVir_av += KVir
            ifr += 1

            norm = float(ifr - skipSteps)

            dU = 2 * f2_av / norm - beta * (f2U_av / norm -
                                            f2_av * U_av / norm**2)
            dU *= const_6
            dU = unit_to_user("energy", unit, dU)

            dK = (Constants.kb * temperature +
                  KPa_av / norm) * f2_av / norm - f2KPa_av / norm
            dK *= const_5
            dK = unit_to_user("energy", unit, dK)

            U = unit_to_user("energy", unit, U_av / norm)
            KVir = unit_to_user("energy", unit, KVir_av / norm)

            iE = open(fn_out_en, "a")
            iE.write(
                "%f    %f     %f     %f     %f    %f     %f     %f     %f     %f\n"
                % (
                    time,
                    KVir + U + dK + dU,
                    KVir + U,
                    dK + dU,
                    U + dU,
                    U,
                    dU,
                    KVir + dK,
                    KVir,
                    dK,
                ))
            iE.close()

        else:
            ifr += 1
def effectiveTemperatures(prefix, temp, ss=0):
    """
    Computes effective temperatures for a given (PI)MD dynamics.
    """

    temperature = unit_to_internal("temperature", "kelvin", float(temp))  # simulation temperature
    skipSteps = int(ss)                                                  # steps to skip for thermalization

    f2_av = None  # average square forces array
    names = None

    fns_for = sorted(glob.glob(prefix + ".for*"))
    fn_out = prefix + ".effective_temperatures.dat"

    nbeads = len(fns_for)

    # print some information
    print 'temperature = {:f} K'.format(float(temp))
    print
    print 'number of beads = {:d}'.format(nbeads)
    print
    print 'forces file names:'
    for fn_for in fns_for:
        print '{:s}'.format(fn_for)
    print
    print 'output file name:'
    print fn_out
    print

    # open input and output files
    ifor = [open(fn, "r") for fn in fns_for]
    iOut = open(fn_out, "w")

    # Some constants
    const = Constants.hbar**2 / (12.0 * (nbeads * Constants.kb * temperature)**3)

    iOut.write("# Atom, Cartesian components of the effective temperature, average effective temperature (in Kelvin)\n")

    natoms = 0
    ifr = 0
    f, m = None, None
    while True:  # Reading input files and calculating PPI correction

        if ifr % 100 == 0:
            print '\rProcessing frame {:d}'.format(ifr),
            sys.stdout.flush()

        try:
            for i in range(nbeads):
                ret = read_file("xyz", ifor[i], dimension='force')["atoms"]
                if natoms == 0:
                    m, natoms, names = ret.m, ret.natoms, ret.names
                    f = np.zeros((nbeads, 3 * natoms))
                    f2_av = np.zeros(3 * natoms)
                f[i, :] = ret.q
        except EOFError:  # finished reading files
            break

        if ifr >= skipSteps:  # PPI correction

            f2 = np.zeros(3 * natoms)
            for i in range(natoms):
                for j in range(nbeads):
                    f2[i * 3:i * 3 + 3] += f[j, i * 3:i * 3 + 3]**2 / m[i]

            f2_av[:] += f2[:]
            ifr += 1

        else:
            ifr += 1

    dT = const * f2_av / float(ifr - skipSteps)

    temperature = unit_to_user("temperature", "kelvin", temperature)

    for i in range(natoms):
        iOut.write("%s    %f     %f     %f     %f\n" % (names[i], temperature * (1 + dT[i * 3]), temperature * (1 + dT[i * 3 + 1]),
                                                        temperature * (1 + dT[i * 3 + 2]), temperature * (1 + np.sum(dT[i * 3:i * 3 + 3]) / 3.0)))

    for f in ifor:
        f.close()

    iOut.close()