Пример #1
0
def qDist(x, y):
    d1 = 0.43
    d2 = 0.85
    if state(x, y) == -1:
        return 0.0
    elif state(x, y) == 1:
        return 1.0
    elif (x - 1.15)**2 + y**2 >= (2.0 * 1.15 - d1)**2:
        return 0.0
    elif (x - 1.15)**2 + y**2 <= d2**2:
        return 1.0
    else:
        return 1.0 - (np.sqrt(
            (x - 1.15)**2 + y**2) - d2) / (2 * 1.15 - d1 - d2)
Пример #2
0
def dqDist(x, y):
    d1 = 0.43
    d2 = 0.85
    if state(x, y) == -1:
        return 0.0, 0.0
    elif state(x, y) == 1:
        return 0.0, 0.0
    elif (x - 1.15)**2 + y**2 >= (2.0 * 1.15 - d1)**2:
        return 0.0, 0.0
    elif (x - 1.15)**2 + y**2 <= d2**2:
        return 0.0, 0.0
    else:
        return -(x - 1.15) / (
            (2 * 1.15 - d1 - d2) * np.sqrt((x - 1.15)**2 + y**2)), -y / (
                (2 * 1.15 - d1 - d2) * np.sqrt((x - 1.15)**2 + y**2))
Пример #3
0
def Lang(ncomm, q0, tstep, temperature, isteps):
    # Define preliminary variables
    q = np.empty((isteps, 2), dtype=np.float64)
    q_trans = np.empty((isteps, 2), dtype=np.float64)
    # Initial conditions
    q[0, 0] = q0[0]
    q[0, 1] = q0[1]
    # Diffusion coefficient
    Dt = np.sqrt(2.0 * temperature * tstep)
    # Index for the transition trajectory
    j = 0
    for i in range(isteps - 1):
        # Evaluate evolution of the system
        fx, fy = force(q[i, 0], q[i, 1])
        q[i + 1, 0] = q[i, 0] + fx * tstep + Dt * np.random.normal(0, 1)
        q[i + 1, 1] = q[i, 1] + fy * tstep + Dt * np.random.normal(0, 1)
        if state(q[i + 1, 0], q[i + 1, 1]) == 0:
            q_trans[j, :] = q[i + 1, :]
            j += 1

    if j == 0:
        out = np.empty((1, 2), dtype=np.float64)
        out[0, 0] = 0.0
        out[0, 1] = 0.0
        return out

    else:
        return q_trans[:j, :]
Пример #4
0
def LangM(ncomm, q0, tstep, temperature, isteps):
    # Define preliminary variables
    q = np.empty((isteps, 2), dtype=np.float64)
    q_trans = np.empty((isteps, 2), dtype=np.float64)
    M = np.empty((isteps, ncomm, ncomm), dtype=np.float64)
    dGx = np.empty(ncomm, dtype=np.float64)
    dGy = np.empty(ncomm, dtype=np.float64)
    # Initial conditions
    q[0, 0] = q0[0]
    q[0, 1] = q0[1]
    # Diffusion coefficient
    Dt = np.sqrt(2.0 * temperature * tstep)
    # Index for the transition trajectory
    j = 0
    for i in range(isteps - 1):
        # Evaluate evolution of the system
        fx, fy = force(q[i, 0], q[i, 1])
        q[i + 1, 0] = q[i, 0] + fx * tstep + Dt * np.random.normal(0, 1)
        q[i + 1, 1] = q[i, 1] + fy * tstep + Dt * np.random.normal(0, 1)
        if state(q[i + 1, 0], q[i + 1, 1]) == 0:
            # Gradient components of the committors
            for k in range(ncomm):
                dGx[k], dGy[k] = ListdGuess(k, q[i + 1, 0], q[i + 1, 1])
            # Evaluating M Matrix
            for k in range(ncomm):
                for l in range(ncomm):
                    M[j, k, l] = dGx[k] * dGx[l] + dGy[k] * dGy[l]
            q_trans[j, :] = q[i + 1, :]
            j += 1

    if j == 0:
        out = np.empty((1, 2), dtype=np.float64)
        out[0, 0] = 0.0
        out[0, 1] = 0.0
        outM = np.empty((1, ncomm, ncomm), dtype=np.float64)
        for k in range(ncomm):
            for l in range(ncomm):
                outM[i, k, l] = 0.0
        return out, outM

    else:
        return q_trans[:j, :], M[:j, :, :]
Пример #5
0
def main():
    print("Algorithm has started")
    ## Parameters of the run
    ncomm = 0  # Number of guess committors
    temperature = 1.0  # Temperature
    tstep = 0.01  # time interval for MD simulations
    kratchet = 150  # Force constant of the ratchet
    MDsteps = 10000  # Maximum number of steps fo MD simulations
    biassim = 1000  # Number of bias simulations used to sample transition region
    selfsteps = 5  # Number of self consistent iterations
    alpha = 0.5  # Percentage of previous iteration in self consistent step
    threshold = 0.001  # Threshold for the end of the self consistent part
    relax = 5  # How often do we pick a point of a biased trajectory as starting point of a MD trajectory
    relaxation = False  # If true, we do a relaxation after we estimate the transition probability with the biased simulations

    ## Limits of the plots
    xlimleft = -2.0
    xlimright = 2.0
    ylimdown = -2.5
    ylimup = 1.5
    delta = 0.025

    ## Name of file if we want to save the evolution of the coefficients of the committor during the self consistent
    savecoeff = False
    namecoeff = ""

    ## Parameters of plots
    axisticslabelfontsize = 9
    axisticslabelfontsizeinset = 7
    axislabelfontsize = 11
    axislabelfontsizeinset = 9
    legendfontsize = 7
    lineswidth = 2
    ncontour = 25
    cmap = plt.get_cmap('RdBu')

    ## Name of file if we want to save the trajectories of the last run
    savetraj = False
    savetraj = ""

    ## Name of file if we want to save transition probability distribution plot
    saveprob = False
    nameprob = ""

    with open("input", "r") as f:
        for line in f:
            line = re.sub("#.*$", "", line)
            line = re.sub(" *$", "", line)
            words = line.split()
            if len(words) == 0:
                continue
            key = words[0]
            if key == "ncomm":
                ncomm = int(words[1])
            elif key == "temperature":
                temperature = float(words[1])
            elif key == "tstep":
                tstep = float(words[1])
            elif key == "kratchet":
                kratchet = float(words[1])
            elif key == "MDsteps":
                MDsteps = int(words[1])
            elif key == "biassim":
                biassim = int(words[1])
            elif key == "selfsteps":
                selfsteps = int(words[1])
            elif key == "alpha":
                alpha = float(words[1])
            elif key == "threshold":
                threshold = float(words[1])
            elif key == "relaxation":
                if re.match("[Tt].*", words[1]):
                    relaxation = True
            elif key == "relax":
                relax = int(words[1])
            elif key == "xlimleft":
                xlimleft = float(words[1])
            elif key == "xlimright":
                xlimright = float(words[1])
            elif key == "ylimdown":
                ylimdown = float(words[1])
            elif key == "ylimup":
                ylimup = float(words[1])
            elif key == "delta":
                delta = float(words[1])
            elif key == "namecoeff":
                savecoeff = True
                namecoeff = words[1]
            elif key == "nametraj":
                savetraj = True
                nametraj = words[1]
            elif key == "nameprob":
                saveprob = True
                nameprob = words[1]
            elif key == "axisticslabelfontsize":
                axisticslabelfontsize = int(words[1])
            elif key == "axisticslabelfontsizeinset":
                axisticslabelfontsizeinset = int(words[1])
            elif key == "axislabelfontsize":
                axislabelfontsize = int(words[1])
            elif key == "axislabelfontsizeinset":
                axislabelfontsizeinset = int(words[1])
            elif key == "legendfontsize":
                legendfontsize = int(words[1])
            elif key == "lineswidth":
                lineswidth = float(words[1])
            elif key == "ncontour":
                ncontour = int(words[1])
            else:
                raise Exception("Unknown keyword: " + key)
    if ncomm == 0:
        raise Exception("Specify the number of guess committors")

    print("Parameters loaded correctly")

    ## Prepare the contour lines for the potential and the basins
    xcontour = np.arange(xlimleft, xlimright, 0.025)
    ycontour = np.arange(ylimdown, ylimup, 0.025)
    X, Y = np.meshgrid(xcontour, ycontour)
    # Potential
    CONT = X * 0
    for i in range(X.shape[0]):
        for j in range(X.shape[1]):
            CONT[i, j] = potential(X[i, j], Y[i, j])
    # Basins
    BASINS = X * 0
    for i in range(X.shape[0]):
        for j in range(X.shape[1]):
            BASINS[i, j] = state(X[i, j], Y[i, j])
    levelsb = [-1.0, 0.0, 1.0]

    ## Prepare the grid for the plots
    yplot, xplot = np.mgrid[slice(ylimdown, ylimup + delta, delta),
                            slice(xlimleft, xlimright + delta, delta)]

    ## I do the self consistent operation
    print("Cycle = ", 1)
    co = np.array([1.0 / ncomm for i in range(ncomm)])
    print(co)
    if savecoeff == True:
        cprint = []
        cprint.append(co)

    print("Cycle = ", 2)
    M = BiasRuns(ncomm, co, tstep, temperature, kratchet, MDsteps, biassim,
                 relaxation, relax)
    print(M)
    c = minimization(co, M, ncomm)
    print(c)
    if savecoeff == True:
        cprint.append(c)

    # I iterate the previous procedure many times
    k = 0
    while k < selfsteps - 2 and np.any(c - co > threshold):
        print("Cycle = ", k + 3)
        M = BiasRuns(ncomm, alpha * c + (1.0 - alpha) * co, tstep, temperature,
                     kratchet, MDsteps, biassim, relaxation, relax)
        print(M)
        cn = minimization(alpha * c + (1.0 - alpha) * co, M, ncomm)
        co = np.copy(c)
        c = np.copy(cn)
        print(c)
        k += 1
        if savecoeff == True:
            cprint.append(c)

    ## I save the coefficients of the linear combination
    if savecoeff == True:
        cprint = np.array(cprint)
        with open(namecoeff, "w") as f:
            np.savetxt(f, cprint, fmt="%10.10f")
        print("Coefficients saved correctly")

    ## Relaxation of the last iteration
    if savetraj == True or saveprob == True:
        tmp = 0
        for j in range(biassim):
            q0 = start_pos()
            biastraj = RatchetLang(c, q0, tstep, temperature, kratchet,
                                   MDsteps)
            if biastraj[0, 0] != 0.0 and biastraj[0, 1] != 0.0:
                q0Lang = biastraj[1::5, :]
                for i in range(q0Lang.shape[0]):
                    traj, M = LangM(ncomm, q0Lang[i, :], tstep, temperature,
                                    relax)  # I run the integrator
                    if traj[0, 0] != 0 and traj[0, 1] != 0:
                        if tmp == 0:
                            trajall = np.copy(traj)
                            Mall = np.copy(M)
                            tmp = 1
                        if tmp == 1:
                            trajall = np.concatenate((trajall, traj), axis=0)
                            Mall = np.concatenate((Mall, M), axis=0)
                    del traj, M
            del biastraj

    M = np.zeros((ncomm, ncomm), dtype=np.float64)
    # Average all the values of M
    for k in range(Mall.shape[0]):
        for i in range(ncomm):
            for j in range(ncomm):
                M[i, j] += Mall[k, i, j]

    # Average M over all the values obtained with the sampling
    M /= Mall.shape[0]

    ## Evaluate the rate
    rate = 0.0
    for i in range(ncomm):
        for j in range(ncomm):
            rate += M[i, j] * c[i] * c[j]
    rate *= np.sqrt(2.0 * temperature)
    print("Rate of optimal linear combination: ", rate)

    ## I do the plot of the Langevin trajectories
    if savetraj == True:
        with PdfPages(nametraj) as pdf:
            fmt1 = '%r %%'
            fig = plt.figure(figsize=(4., 2.8))
            plt.rc('text')
            panel = fig.add_axes([
                0.15, 0.15, 0.72, 0.75
            ])  # dimensions and location of the panel within the figure
            # Potential
            pcm = panel.plot(trajall[:, 0],
                             trajall[:, 1],
                             linewidth=0.5,
                             zorder=10)
            panel.set_xlabel(
                r'$x$', fontsize=axislabelfontsize, labelpad=2
            )  # labels and ticklabels along x with their fontsize and location, x limits and same for y below
            for tick in panel.xaxis.get_major_ticks():
                tick.label.set_fontsize(axisticslabelfontsize)
            panel.set_xlim(xlimleft - delta, xlimright + delta)
            panel.xaxis.set_major_locator(MultipleLocator(1))
            panel.xaxis.set_minor_locator(MultipleLocator(0.2))
            panel.set_ylabel(r'$y$', fontsize=axislabelfontsize, labelpad=2)
            for tick in panel.yaxis.get_major_ticks():
                tick.label.set_fontsize(axisticslabelfontsize)
            panel.set_ylim(ylimdown - delta, ylimup + delta)
            panel.yaxis.set_major_locator(MultipleLocator(1))
            panel.yaxis.set_minor_locator(MultipleLocator(0.2))
            CS = panel.contour(X,
                               Y,
                               CONT,
                               ncontour,
                               colors='k',
                               linewidths=0.5,
                               zorder=0)
            plt.clabel(CS, fontsize=4, inline=1)
            contour = panel.contour(X,
                                    Y,
                                    BASINS,
                                    levels=levelsb,
                                    colors="orange",
                                    linewidths=0.5,
                                    linestyles='dashed',
                                    zorder=5)
            plt.title("Trajectories")  # title
            pdf.savefig(fig)
        print("Trajectories plotted successfully")

    ## I do the plot of the probability distribution in the transition region
    if saveprob == True:
        with PdfPages(nameprob) as pdf:
            fmt1 = '%r %%'
            fig = plt.figure(figsize=(4., 2.8))
            plt.rc('text')
            panel = fig.add_axes([
                0.15, 0.15, 0.72, 0.75
            ])  # dimensions and location of the panel within the figure
            # Borders of the plot
            xedges = np.arange(xlimleft, xlimright, delta).tolist()
            yedges = np.arange(ylimdown, ylimup, delta).tolist()
            # Create the histogram
            H, xedges, yedges = np.histogram2d(trajall[:, 0],
                                               trajall[:, 1],
                                               bins=(xedges, yedges),
                                               density=True)
            H = H.T  # Let each row list bins with common y range.
            pcm = panel.imshow(
                H,
                interpolation='nearest',
                origin='low',
                extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]])
            cbar = plt.colorbar(pcm, format=ticker.FuncFormatter(
                fmt))  # plot colorbar and select format
            cbar.ax.tick_params(labelsize=axisticslabelfontsize -
                                2)  # dimension of the labels of the colorbar
            pcm.set_cmap('RdBu')
            panel.set_xlabel(
                r'$x$', fontsize=axislabelfontsize, labelpad=2
            )  # labels and ticklabels along x with their fontsize and location, x limits and same for y below
            for tick in panel.xaxis.get_major_ticks():
                tick.label.set_fontsize(axisticslabelfontsize)
            panel.set_xlim(xlimleft - delta, xlimright + delta)
            panel.xaxis.set_major_locator(MultipleLocator(1))
            panel.xaxis.set_minor_locator(MultipleLocator(0.2))
            panel.set_ylabel(r'$y$', fontsize=axislabelfontsize, labelpad=2)
            for tick in panel.yaxis.get_major_ticks():
                tick.label.set_fontsize(axisticslabelfontsize)
            panel.set_ylim(ylimdown - delta, ylimup + delta)
            panel.yaxis.set_major_locator(MultipleLocator(1))
            panel.yaxis.set_minor_locator(MultipleLocator(0.2))
            # Potential
            CS = panel.contour(X,
                               Y,
                               CONT,
                               ncontour,
                               colors='k',
                               linewidths=0.5)
            plt.clabel(CS, fontsize=4, inline=1)
            contour = panel.contour(X,
                                    Y,
                                    BASINS,
                                    levels=levelsb,
                                    colors="white",
                                    linewidths=0.5,
                                    linestyles='dashed')
            plt.title("Transition probability distribution")  # title
            pdf.savefig(fig)
        print("Transition probability distribution plotted successfully")
Пример #6
0
def RatchetLangM(c, q0, tstep, temperature, kr, isteps):
    ## Number of committor functions given as input
    ncomm = len(c)
    # Define preliminary variables
    q = np.empty((isteps, 2), dtype=np.float64)
    M = np.empty((isteps, ncomm, ncomm), dtype=np.float64)
    dGx = np.empty(ncomm, dtype=np.float64)
    dGy = np.empty(ncomm, dtype=np.float64)
    # Assign initial position to the border of the reactant state
    q[0, 0] = q0[0]
    q[0, 1] = q0[1]
    # Incremental variables in the loop
    i = 0
    j = 0
    tmp = 0
    # State of the point. If in reactant = -1, if in product = 1, otherwise = 0
    s = state(q[0, 0], q[1, 1])
    zmax = 0.0
    # Diffusion coefficient
    Dt = np.sqrt(2.0 * temperature * tstep)
    while i < isteps - 1 and tmp == 0:
        if s == -1:
            # Restart trajectory
            j = i
        elif s == 1:
            #Exit from loop
            tmp = 1
        # Evaluate evolution of the system
        fx, fy = force(q[i, 0], q[i, 1])
        # Evaluate z
        z = 0.0
        for k in range(ncomm):
            z += c[k] * ListGuess(k, q[i, 0], q[i, 1])
        # Gradient components of the committors
        for k in range(ncomm):
            dGx[k], dGy[k] = ListdGuess(k, q[i, 0], q[i, 1])
        # Evaluating M Matrix
        for k in range(ncomm):
            for l in range(ncomm):
                M[i, k, l] = dGx[k] * dGx[l] + dGy[k] * dGy[l]
        # Dynamics
        if z > zmax:
            q[i + 1, 0] = q[i, 0] + fx * tstep + Dt * np.random.normal(0, 1)
            q[i + 1, 1] = q[i, 1] + fy * tstep + Dt * np.random.normal(0, 1)
            zmax = z
        else:
            ratchetx = 0.0
            ratchety = 0.0
            for k in range(ncomm):
                ratchetx += c[k] * dGx[k]
                ratchety += c[k] * dGy[k]
            q[i + 1, 0] = q[i, 0] + fx * tstep + Dt * np.random.normal(
                0, 1) + kr * ratchetx * (zmax - z) * tstep
            q[i + 1, 1] = q[i, 1] + fy * tstep + Dt * np.random.normal(
                0, 1) + kr * ratchety * (zmax - z) * tstep
        i += 1
        s = state(q[i, 0], q[i, 1])

    # Output in the case we do not find a reactive coordinate, so that the function does not crash
    if tmp == 0:
        print('No reactive trajectory found!')
        out = np.empty((1, 2), dtype=np.float64)
        out[0, 0] = 0.0
        out[0, 1] = 0.0
        outM = np.empty((1, ncomm, ncomm), dtype=np.float64)
        for k in range(ncomm):
            for l in range(ncomm):
                outM[i, k, l] = 0.0
        return out, outM

    return q[j + 1:i - 1, :], M[j + 1:i - 1, :, :]
Пример #7
0
def main():

    print("Algorithm has started")
    ## Parameters of the run
    temperature = 1.0  # Temperature
    diffusion = 1.0  # diffusion coefficient
    tstep = 0.01  # time interval for MD simulations
    Nsim = 1000  # Number of MD simulations to determine boundary conditions
    stepsim = 5000  # maximum number of steps for MD simulations

    ## Parameters of the grid
    xlimleft = -3.0
    xlimright = 3.0
    nxstep = 50
    ylimdown = -3.0
    ylimup = 3.0
    nystep = 50

    ## Name of file if we want to save the committor
    savefile = False
    namefile = ""

    ## Parameters if we want to save committor plot
    saveplot = False
    nameplot = ""
    axisticslabelfontsize = 9
    axisticslabelfontsizeinset = 7
    axislabelfontsize = 11
    axislabelfontsizeinset = 9
    legendfontsize = 7
    lineswidth = 2
    ncontour = 25

    with open("input", "r") as f:
        for line in f:
            line = re.sub("#.*$", "", line)
            line = re.sub(" *$", "", line)
            words = line.split()
            if len(words) == 0:
                continue
            key = words[0]
            if key == "temperature":
                temperature = float(words[1])
            elif key == "diffusion":
                diffusion = float(words[1])
            elif key == "tstep":
                tstep = float(words[1])
            elif key == "Nsim":
                Nsim = int(words[1])
            elif key == "stepsim":
                stepsim = int(words[1])
            elif key == "tstep":
                tstep = float(words[1])
            elif key == "xlimleft":
                xlimleft = float(words[1])
            elif key == "xlimright":
                xlimright = float(words[1])
            elif key == "nxstep":
                nxstep = int(words[1])
            elif key == "ylimup":
                ylimup = float(words[1])
            elif key == "ylimdown":
                ylimdown = float(words[1])
            elif key == "nystep":
                nystep = int(words[1])
            elif key == "namefile":
                savefile = True
                namefile = words[1]
            elif key == "nameplot":
                saveplot = True
                nameplot = words[1]
            elif key == "axisticslabelfontsize":
                axisticslabelfontsize = int(words[1])
            elif key == "axisticslabelfontsizeinset":
                axisticslabelfontsizeinset = int(words[1])
            elif key == "axislabelfontsize":
                axislabelfontsize = int(words[1])
            elif key == "axislabelfontsizeinset":
                axislabelfontsizeinset = int(words[1])
            elif key == "legendfontsize":
                legendfontsize = int(words[1])
            elif key == "lineswidth":
                lineswidth = float(words[1])
            elif key == "ncontour":
                ncontour = int(words[1])
            else:
                raise Exception("Unknown keyword: " + key)

    print("Parameters loaded correctly")

    x = np.linspace(xlimleft, xlimright, nxstep)
    y = np.linspace(ylimdown, ylimup, nystep)
    beta = 1.0 / temperature  # 1/k_{B}T
    dx = x[1] - x[0]  # step of the grid along the x direction
    dy = y[1] - y[0]  # step of the grid along the y direction
    I = len(x) - 1  # index of the last cell along x
    J = len(y) - 1  # index of the last cell along y
    N = I * (
        J + 1
    ) + J  # index of the last cell in the 1D vector that contains all the I*(J+1)+J+1 = N+1 cells in the system
    q = np.zeros(
        shape=(N + 1)
    )  # vector that contains the N+1 values of the committor for each grid point
    P = np.zeros(
        shape=(N + 1, N + 1)
    )  # matrix with (N+1)*(N+1) elements, that determines the linear system to solve P*q = R
    R = np.zeros(shape=(
        N + 1
    ))  # vector with the N+1 elements of results of the backward F-P equation
    bd = 0  # counter for boundary points on which the MD is finished

    ## Precompute some coefficients
    D1 = diffusion * beta * tstep
    D2 = np.sqrt(2. * diffusion * tstep)

    print("Total number of boundary points = ", 2 * (nxstep + nystep) - 4)
    now = time.time()
    # construction of P and R
    i = 0
    while i < len(x):
        xp = x[i]
        j = 0
        while j < len(y):
            yp = y[j]
            Fx, Fy = force(xp, yp)
            n = i * (
                J + 1
            ) + j  # for each grid point i,j computes the corresponding index n in the 1D vectors and computes the coefficients A,B,C,D,E
            A = diffusion / (dx**2) + (beta * diffusion * Fx) / (2 * dx)
            B = 2. * diffusion / (dx**2) + 2. * diffusion / (dy**2)
            C = diffusion / (dx**2) - (beta * diffusion * Fx) / (2 * dx)
            D = diffusion / (dy**2) + (beta * diffusion * Fy) / (2 * dy)
            E = diffusion / (dy**2) - (beta * diffusion * Fy) / (2 * dy)
            if state(
                    xp, yp
            ) != 0:  # if you are inside the reactant basin or the product basin impose boundary condition of q = 0 in Reactant and q = 1 in Product
                P[n, n] = 1.
                if xp > 0.:
                    R[n] = 1.
            elif (
                (i == 0) or (i == I)
            ):  # if you are on the two boundaries along x, do MD simulations for each boundary point to find the committor on the edges of the grid
                t = 0
                nr = 0
                nt = 0
                while t < Nsim:  # 1000 trajectories for each point
                    xi = x[
                        i]  # for each trajectory in a given grid point on the edge, set as initial conditions the coordinates of that grid point
                    yi = y[j]
                    k = 0
                    while (
                            state(xi, yi) == 0 and k < stepsim
                    ):  # keep evolving the system untill you enter in Reactant or Product
                        Fx, Fy = force(xi, yi)
                        xf = xi + Fx * D1 + D2 * np.random.normal(
                            loc=0., scale=1.
                        )  # evolve x and y with the equations of motion for a passive particle performing brownian motion in a potential energy landscape
                        yf = yi + Fy * D1 + D2 * np.random.normal(loc=0.,
                                                                  scale=1.)
                        xi = xf
                        yi = yf
                        k += 1
                    if xf < 0.:  # if you enter in Reactant
                        nr += 1
                    elif xf > 0.:  # if you enter in Product
                        nt += 1
                    t += 1
                if t != (nt + nr):  # just a check
                    print("Something wrong occurred during MD simulation!")
                bd += 1
                print(
                    bd
                )  # print the index of the boundary point in which you finished the MD simulations
                P[n, n] = 1.
                R[n] = nt / (nt + nr)  # value of the committor in that point
            elif (
                (i != 0) and (i != I) and ((j == 0) or (j == J))
            ):  # if you are on the boundaries along y do MD simulation for each grid point on the boundary, except those included in the boundaries of x that are already done
                t = 0
                nr = 0
                nt = 0
                while t < Nsim:
                    xi = x[i]
                    yi = y[j]
                    k = 0
                    while (state(xi, yi) == 0 and k < stepsim):
                        Fx, Fy = force(xi, yi)
                        xf = xi + Fx * D1 + D2 * np.random.normal(loc=0.,
                                                                  scale=1.)
                        yf = yi + Fy * D1 + D2 * np.random.normal(loc=0.,
                                                                  scale=1.)
                        xi = xf
                        yi = yf
                        k += 1
                    if xf < 0.:
                        nr += 1
                    elif xf > 0.:
                        nt += 1
                    t += 1
                if t != (nt + nr):
                    print("Something wrong occurred during MD simulation!")
                bd += 1
                print(bd)
                P[n, n] = 1.
                R[n] = nt / (nt + nr)
            else:  # if you are in every other point of the grid fill the P matrix according to the usual pattern
                P[n, (i - 1) * (J + 1) + j] = C
                P[n, i * (J + 1) + j - 1] = E
                P[n, i * (J + 1) + j] = -B
                P[n, i * (J + 1) + j + 1] = D
                P[n, (i + 1) * (J + 1) + j] = A
            j += 1
        i += 1

    print("System initialized")

    q = scipy.linalg.solve(P, R)  # solve linear system to find the committor
    for el in q:
        if el > 1.:  # some errors in the solution of the system are inevitable, so don't mind if you get some of these errors, as long as the values of the committor are not too much larger than 1 or too much smaller than 0
            print("Error! Committor larger than 1!")
        elif el < 0.:
            print("Error! Committor smaller than 0!")
    q = np.reshape(
        q, (I + 1, J + 1))  # reshape the committor from 1D vector to 2D grid

    print("Simulation time ", time.time() - now)

    # Save committor on a File
    if savefile == True:
        with open(namefile, "w") as f:
            np.savetxt(f, q, fmt="%10.10f")
        print("Committor saved correctly")

    # Make the plot
    if saveplot == True:
        xplot = np.empty(shape=(
            len(x) + 1
        ))  # set x and y coordinates for the edges of the bins in the grid
        yplot = np.empty(shape=(len(y) + 1))
        k = 0
        for el in x:
            xplot[k] = x[k] - (dx / 2.)
            k += 1
        xplot[len(x)] = x[len(x) - 1] + (dx / 2.)
        k = 0
        for el in y:
            yplot[k] = y[k] - (dy / 2.)
            k += 1
        yplot[len(y)] = y[len(y) - 1] + (dy / 2.)

        with PdfPages(nameplot) as pdf:
            fmt1 = '%r %%'
            fig = plt.figure(figsize=(4., 2.8), dpi=600)
            plt.rc('text')
            panel = fig.add_axes([
                0.15, 0.15, 0.72, 0.75
            ])  # dimensions and location of the panel within the figure
            cmap = plt.get_cmap('RdBu')  # choose colormap for the committor
            pcm = panel.pcolormesh(xplot,
                                   yplot,
                                   q.T,
                                   cmap=cmap,
                                   zorder=0,
                                   vmin=0.,
                                   vmax=1.)  # plot the committor in the grid
            cbar = plt.colorbar(pcm, format=ticker.FuncFormatter(
                fmt))  # plot colorbar and select format
            cbar.ax.tick_params(labelsize=axisticslabelfontsize -
                                2)  # dimension of the labels of the colorbar
            panel.set_xlabel(
                r'$x$', fontsize=axislabelfontsize, labelpad=2
            )  # labels and ticklabels along x with their fontsize and location, x limits and same for y below
            for tick in panel.xaxis.get_major_ticks():
                tick.label.set_fontsize(axisticslabelfontsize)
            panel.set_xlim(xlimleft - 0.1, xlimright + 0.1)
            panel.xaxis.set_major_locator(MultipleLocator(1))
            panel.xaxis.set_minor_locator(MultipleLocator(0.2))
            panel.set_ylabel(r'$y$', fontsize=axislabelfontsize, labelpad=2)
            for tick in panel.yaxis.get_major_ticks():
                tick.label.set_fontsize(axisticslabelfontsize)
            panel.set_ylim(ylimdown - 0.1, ylimup + 0.1)
            panel.yaxis.set_major_locator(MultipleLocator(1))
            panel.yaxis.set_minor_locator(MultipleLocator(0.2))
            # Grid for contour lines
            x = np.arange(xlimleft, xlimright, 0.025)
            y = np.arange(ylimdown, ylimup, 0.025)
            X, Y = np.meshgrid(x, y)
            # Potential contour lines
            Z = X * 0
            for i in range(X.shape[0]):
                for j in range(X.shape[1]):
                    Z[i, j] = potential(X[i, j], Y[i, j])
            CS = panel.contour(X, Y, Z, ncontour, colors='k', linewidths=0.5)
            plt.clabel(CS, fontsize=4, inline=1)
            # Basins contour lines
            P = X * 0
            for i in range(X.shape[0]):
                for j in range(X.shape[1]):
                    P[i, j] = state(X[i, j], Y[i, j])
            levelsb = [-1.0, 0.0, 1.0]
            contour = panel.contour(X,
                                    Y,
                                    P,
                                    levels=levelsb,
                                    colors="white",
                                    linewidths=0.5,
                                    linestyles='dashed')
            plt.title(r"$q(x,y)$")  # title
            pdf.savefig(fig)

        print("Committor plot saved correctly")