Example #1
0
def heatCapacity(prefix, temp, ss=0):
    """
    Computes a primitive estimator for the heat capacity 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

    # some required sums
    KPa_av, U_av, f2_av, f2KPa_av, f2U_av, E2_av, f2E_av, f2E2_av = (
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
    )

    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 + ".heat_capacity.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")
    iC = 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 = Constants.kb ** 2 / Constants.hbar ** 2
    const_4 = Constants.hbar ** 2 * beta ** 2 / (24.0 * nbeads ** 3)
    const_5 = Constants.kb * beta ** 2

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

    iC.write(
        "# Simulation time (in %s), improved heat capacity estimator, primitive heat capacity estimator, "
        "and PPI correction for the heat capacity\n" % timeUnit
    )
    iC.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 = 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]
                        )

                KPa *= const_1
                KPa += const_2 * 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,
                )

                KPa *= const_3
                KPa += const_2 * natoms

            f2_av += f2
            KPa_av += KPa
            f2KPa_av += f2 * KPa
            U_av += U
            f2U_av += f2 * U
            E2_av += (KPa + U) ** 2
            f2E2_av += f2 * (KPa + U) ** 2
            ifr += 1

            norm = float(ifr - skipSteps)

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

            dK = f2_av / norm - beta * (f2KPa_av / norm - f2_av * KPa_av / norm ** 2)
            dK *= const_4

            C = (
                E2_av / norm
                - ((KPa_av + U_av) / norm) ** 2
                + (2.0 / beta) * KPa_av / norm
                - 1.5 * nbeads * natoms / beta ** 2
            )
            C *= const_5

            dC = (
                2
                * (5 + 3 * beta * (KPa_av + U_av) / norm)
                * beta
                * f2_av
                * const_4
                / norm
                - 2 * (3 + beta * (KPa_av + U_av) / norm) * beta * (dK + dU)
                + 2 * beta * dK
                - const_4 * (f2E2_av / norm - f2_av * E2_av / norm ** 2) * beta ** 3
            )

            iC = open(fn_out_en, "a")
            iC.write("%f    %f     %f     %f\n" % (time, C + dC, C, dC))
            iC.close()

        else:
            ifr += 1
Example #2
0
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 kineticEnergy(prefix, temp, ss=0, unit=""):
    """
    Computes the virial centroid estimator for the kinetic 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

    f2_av, KPa_av, KVir_av, f2KPa_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 + ".kinetic_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, 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 kinetic energy and PPI kinetic energy corrections (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), end=" ")
            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"]
            time = read_time(iU, 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
            KVir_av += KVir
            ifr += 1

            norm = float(ifr - skipSteps)

            dK = (Constants.kb * temperature +
                  KPa_av / norm) * f2_av / norm - f2KPa_av / norm
            dK *= const_5

            dK = unit_to_user("energy", unit, dK)
            eVir = unit_to_user("energy", unit, KVir_av / norm)

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

        else:
            ifr += 1
Example #4
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),
            sys.stdout.flush()

        try:
            for i in range(nbeads):
                ret = read_file("xyz", ipos[i])
                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])["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

    # 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[:, 1] *= const / nbeads
    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)
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
Example #6
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), 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
Example #7
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
Example #8
0
def heatCapacity(prefix, temp, ss=0):
    """
    Computes a primitive estimator for the heat capacity 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

    # some required sums
    KPa_av, U_av, f2_av, f2KPa_av, f2U_av, E2_av, f2E_av, f2E2_av = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0

    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 + ".heat_capacity.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")
    iC = 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 = Constants.kb**2 / Constants.hbar**2
    const_4 = Constants.hbar**2 * beta**2 / (24.0 * nbeads**3)
    const_5 = Constants.kb * beta**2

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

    iC.write("# Simulation time (in %s), improved heat capacity estimator, primitive heat capacity estimator, "
             "and PPI correction for the heat capacity\n" % timeUnit)
    iC.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 = 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]

                KPa *= const_1
                KPa += const_2 * 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)

                KPa *= const_3
                KPa += const_2 * natoms

            f2_av += f2
            KPa_av += KPa
            f2KPa_av += f2 * KPa
            U_av += U
            f2U_av += f2 * U
            E2_av += (KPa + U)**2
            f2E2_av += f2 * (KPa + U)**2
            ifr += 1

            norm = float(ifr - skipSteps)

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

            dK = f2_av / norm - beta * (f2KPa_av / norm - f2_av * KPa_av / norm**2)
            dK *= const_4

            C = E2_av / norm - ((KPa_av + U_av) / norm)**2 + (2.0 / beta) * KPa_av / norm - 1.5 * nbeads * natoms / beta**2
            C *= const_5

            dC = 2 * (5 + 3 * beta * (KPa_av + U_av) / norm) * beta * f2_av * const_4 / norm - \
                2 * (3 + beta * (KPa_av + U_av) / norm) * beta * (dK + dU) + 2 * beta * dK - \
                const_4 * (f2E2_av / norm - f2_av * E2_av / norm**2) * beta**3

            iC = open(fn_out_en, "a")
            iC.write("%f    %f     %f     %f\n" % (time, C + dC, C, dC))
            iC.close()

        else:
            ifr += 1
Example #9
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
Example #10
0
def heat_capacity(prefix, temp, ss=0):
    """
  Computes a virial centroid estimator for the heat capacity 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

    # some required sums
    KPa_av, KVir_av, U_av, f2_av, f2KPa_av, f2U_av, EVir_av, EEVir_av, f2E_av, f2E2_av = \
      0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0

    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 + ".heat_capacity.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")
    iC = 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)
    const_7 = Constants.kb * beta**2

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

    iC.write(
        "# Simulation time (in %s), centroid virial heat capacity estimator and PPI correction\n"
        % timeUnit)

    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

            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
            EVir_av += KVir + U
            EEVir_av += (KVir + U) * (KPa + U)
            f2E_av += f2 * (KPa + U)
            f2E2_av += f2 * (KPa + U)**2
            ifr += 1

            norm = float(ifr - skipSteps)

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

            dK = (Constants.kb * temperature +
                  KPa_av / norm) * f2_av / norm - f2KPa_av / norm
            dK *= const_5

            C = EEVir_av / norm - (EVir_av / norm)**2 + 1.5 * natoms / beta**2
            C *= const_7

            dC = (10 + C + 3*beta*EVir_av/norm)*beta*f2_av*const_6/norm - \
                 (6 + beta*EVir_av/norm)*beta*(dK + dU) + 2*beta*dK - \
                 const_6*(f2E2_av/norm - f2E_av*(KPa_av + U_av)/norm**2)*beta**3

            iC.write("%f    %f     %f\n" % (time, C, dC))

        else:
            ifr += 1