Esempio n. 1
0
def accept(s, q_old, q_new, w_old=1.0, w_new=1.0):
    """Returns accept/reject decision based on supplied entropy table."""

    import numpy as np
    from maths_module import metropolis

    # This routine is essentially the Metropolis-Hastings formula, generalized
    # to use a specified tabulated function of the energy in the exponent
    # For NVT MC, s(q) is just E(q)/kT = -q/kT since energy is -q
    # For Wang-Landau, s(q) is the entropy function, which is updated through the run
    # In either case, weights (real, but taking positive integer values here) may optionally appear

    w_tol = np.float_(0.5)

    # Check that we are within bounds for the entropy table
    assert q_new >= 0 and q_new < s.size, 'q_new out of bounds'
    assert q_old >= 0 and q_old < s.size, 'q_old out of bounds'

    # Check values of weights
    assert w_old > w_tol, 'Impossible weight error'
    if w_new < w_tol:  # Should really have been detected before
        return False

    delta = s[q_new] - s[q_old]  # Change in entropy function

    # Equivalent to exp(-delta) -> (w_new/w_old)*exp(-delta)
    delta = delta - np.log(w_new / w_old)

    result = metropolis(delta)
    return result
            for k in range(p):  # Loop over ring polymer indices
                rkj = np.delete(r[k, :, :], i,
                                0)  # Array of all other atoms for this k
                partial_old = partial_old + potential_1(
                    r[k, i, :], box, r_cut, rkj,
                    p)  # Old atom classical potential etc
                rki = r[k, i, :] + dc
                rki = rki - np.rint(rki)
                partial_new = partial_new + potential_1(
                    rki, box, r_cut, rkj,
                    p)  # New atom classical potential etc
            assert not partial_old.ovr, 'Overlap in current configuration'
            if not partial_new.ovr:  # Test for non-overlapping configuration
                delta = partial_new.pot - partial_old.pot  # Change in classical cut (but not shifted) potential
                delta = delta / temperature
                if metropolis(delta):  # Accept Metropolis test
                    total = total + partial_new - partial_old  # Update total values
                    r[:, i, :] = r[:, i, :] + dc  # Update positions
                    r[:, i, :] = r[:, i, :] - np.rint(
                        r[:, i, :])  # Periodic boundary conditions
                    c_moves = c_moves + 1  # Increment move counter

            # Individual atom moves
            for k in range(p):  # Loop over ring polymer indices
                rkj = np.delete(r[k, :, :], i,
                                0)  # Array of all the other atoms
                partial_old = potential_1(
                    r[k, i, :], box, r_cut, rkj,
                    p)  # Old atom classical potential etc
                assert not partial_old.ovr, 'Overlap in current configuration'
            rj = np.delete(r, i, 0)  # Array of all the other atoms
            partial_old = potential_1(r[i, :], box, r_cut,
                                      rj)  # Old atom potential, virial etc
            assert not partial_old.ovr, 'Overlap in current configuration'

            ri = random_translate_vector(
                dr_max / box,
                r[i, :])  # Trial move to new position (in box=1 units)
            ri = ri - np.rint(ri)  # Periodic boundary correction
            partial_new = potential_1(ri, box, r_cut,
                                      rj)  # New atom potential, virial etc

            if not partial_new.ovr:  # Test for non-overlapping configuration
                delta = partial_new.pot - partial_old.pot  # Use cut (but not shifted) potential
                delta = delta / temperature
                if metropolis(delta):  # Accept Metropolis test
                    total = total + partial_new - partial_old  # Update total values
                    r[i, :] = ri  # Update position
                    moves = moves + 1  # Increment move counter

        m_ratio = moves / n

        x_ratio = 0.0
        for updown in range(2):  # Loop to look one way then the other
            if m % 2 == updown:  # Look up, partner is m+1
                if m + 1 < nproc:  # Ensure partner exists
                    other_beta = every_beta[
                        m + 1]  # We already know the other beta
                    other_pot = comm.recv(
                        source=m + 1,
                        tag=msg1_id)  # Receive pot from other process