示例#1
0
def test_optimizers(opt_cls, opt_kwargs_, ref_cycle):
    geom = AnaPot.get_geom((0.667, 1.609, 0.))
    ref_coords = np.array((1.941, 3.8543, 0.))

    opt_kwargs = {
        "thresh": "gau_tight",
        "dump": False,
        "overachieve_factor": 2.,
    }
    opt_kwargs.update(opt_kwargs_)
    opt = opt_cls(geom, **opt_kwargs)
    opt.run()

    # import matplotlib.pyplot as plt
    # calc = geom.calculator
    # calc.plot()
    # coords = np.array(opt.coords)
    # ax = calc.ax
    # ax.plot(*coords.T[:2], "ro-")
    # plt.show()

    assert opt.is_converged
    assert opt.cur_cycle == ref_cycle

    diff = ref_coords - geom.coords
    diff_norm = np.linalg.norm(diff)
    print(f"@\tnorm(diff)={diff_norm:.8f}")
    assert diff_norm < 6e-5
示例#2
0
def test_sqnm():
    # geom = AnaPot.get_geom((0, 4, 0))
    geom = AnaPot.get_geom((-0.8, 1.73, 0))

    opt_kwargs = {
        "max_cycles": 15,
        "eps": 1e-4,
        "E_thresh": 1e-4,
        "alpha": 0.5,
        "hist_max": 10,
        # "thresh": "gau_tight",
        "trust_radius": 0.1,
        # "bio": False,
        "dump": True,
    }
    opt = StabilizedQNMethod(geom, **opt_kwargs)
    # opt = SQNM3(geom, **opt_kwargs)
    opt.run()
    c = np.array(opt.coords)
    calc = geom.calculator
    calc.plot()
    ax = calc.ax
    ax.plot(c[:, 0], c[:, 1], "o-")

    plt.show()
示例#3
0
def run_lanczos():
    x0 = (-0.5767, 1.6810, 0)
    geom0 = AnaPot.get_geom(x0)
    w_min, v_min = lanczos(geom0, dx=1e-5)
    H = geom0.hessian
    w, v = np.linalg.eigh(H)
    w_min_ref = w[0]
    print(f"w_min_ref={w_min_ref:.6f}")
示例#4
0
def test_anapot_lanczos():
    geom = AnaPot.get_geom((-0.5767, 1.6810, 0.))
    guess = (0.4, 0.3, 0.0)
    w_min, v_min = geom_lanczos(geom, guess=guess, dx=1e-5, dl=1e-5, logger=logger)

    H = geom.hessian
    w, v = np.linalg.eigh(H)
    w_ref = w[0]
    v_ref = v[:,0]
    assert w_min == pytest.approx(w_ref, abs=1e-4)
    assert any([np.allclose(v, v_ref, atol=5e-2) for v in (v_min, -v_min)])
示例#5
0
def ase_md_playground():
    geom = AnaPot.get_geom((0.52, 1.80, 0), atoms=("H", ))
    atoms = geom.as_ase_atoms()
    # ase_calc = FakeASE(geom.calculator)
    # from ase.optimize import BFGS
    # dyn = BFGS(atoms)
    # dyn.run(fmax=0.05)

    import ase
    from ase import units
    from ase.io.trajectory import Trajectory
    from ase.md.velocitydistribution import MaxwellBoltzmannDistribution
    from ase.md.verlet import VelocityVerlet

    MaxwellBoltzmannDistribution(atoms, 300 * units.kB)
    momenta = atoms.get_momenta()
    momenta[0, 2] = 0.
    # Zero 3rd dimension
    atoms.set_momenta(momenta)

    dyn = VelocityVerlet(atoms, .005 * units.fs)  # 5 fs time step.


    def printenergy(a):
        """Function to print the potential, kinetic and total energy"""
        epot = a.get_potential_energy() / len(a)
        ekin = a.get_kinetic_energy() / len(a)
        print('Energy per atom: Epot = %.3feV  Ekin = %.3feV (T=%3.0fK)  '
              'Etot = %.3feV' % (epot, ekin, ekin / (1.5 * units.kB), epot + ekin))

    # Now run the dynamics
    printenergy(atoms)
    traj_fn = 'asemd.traj'
    traj = Trajectory(traj_fn, 'w', atoms)
    dyn.attach(traj.write, interval=5)
    # dyn.attach(bumms().bimms, interval=1)

    dyn.run(10000)
    printenergy(atoms)
    traj.close()

    traj = ase.io.read(traj_fn+"@:")#, "r")
    pos = [a.get_positions() for a in traj]
    from pysisyphus.constants import BOHR2ANG
    pos = np.array(pos) / BOHR2ANG

    calc = geom.calculator
    calc.plot()

    ax = calc.ax
    ax.plot(*pos[:,0,:2].T)

    plt.show()
示例#6
0
def test_tshessian_opts(opt_cls, ref_cur_cycle):
    geom = AnaPot.get_geom((-0.6, 2.2, 0.))

    opt_kwargs = {
        "trust_radius": 0.2,
        "dump": False,
    }
    opt = opt_cls(geom, **opt_kwargs)
    opt.run()

    assert opt.is_converged
    assert opt.cur_cycle == ref_cur_cycle
示例#7
0
def test_anapot_growing_string(keep_last, ref_cycle):
    initial = AnaPot.get_geom((-1.05274, 1.02776, 0))
    final = AnaPot.get_geom((1.94101, 3.85427, 0))
    geoms = (initial, final)
    gs_kwargs = {
        "perp_thresh": 0.5,
        "reparam_check": "rms",
    }
    gs = GrowingString(geoms, lambda: AnaPot(), **gs_kwargs)

    opt_kwargs = {
        # "stop_in_when_full": 3,
        "stop_in_when_full": keep_last,
        "keep_last": keep_last,
    }
    opt = StringOptimizer(gs, **opt_kwargs)
    opt.run()

    # calc = AnaPot()
    # calc.anim_opt(opt, show=True)

    assert opt.is_converged
    assert opt.cur_cycle == ref_cycle
示例#8
0
def run_opt(line_search=False, hessian_recalc=None):
    geom = AnaPot.get_geom((0.667, 1.609, 0.))

    rfo_kwargs = {
        "trust_radius": 0.75,
        "thresh": "gau_tight",
        "hessian_recalc": hessian_recalc,
        "line_search": line_search,
        # "hessian_init": "calc",
    }
    rfo = RFOptimizer(geom, **rfo_kwargs)
    rfo.run()
    conv = rfo.is_converged
    cycs = rfo.cur_cycle
    return (conv, cycs)
示例#9
0
def test_fs():
    from pysisyphus.calculators.XTB import XTB
    from pysisyphus.cos.FreezingString import FreezingString
    # educt = geom_from_library("ciscis_24hexadiene_xtbopt.xyz")
    # product = geom_from_library("trans34dimethylcyclobutene.xyz")

    educt = AnaPot.get_geom((-1.05274, 1.02776, 0))
    product = AnaPot.get_geom((1.94101, 3.85427, 0))
    images = (educt, product)
    
    def calc_getter():
        return AnaPot()

    fs = FreezingString(images, calc_getter, max_nodes=10)
    from pysisyphus.optimizers.SteepestDescent import SteepestDescent
    sd = SteepestDescent(fs)
    sd.run()
    pot = AnaPot()
    pot.plot()
    crds = fs.allcoords.reshape(-1, 3)
    # pot.ax.plot(c[:,0], c[:,1], "o-")
    pot.ax.plot(*crds[:,:2].T, "o-")
    plt.show()
    from pysisyphus.optimizers.StringOptimizer import StringOptimizer
示例#10
0
def test_add_gaussian():
    geom = AnaPot.get_geom((-0.2, 1.1, 0))
    N_raw = np.array((0.3, 0.7, 0.))

    calc = geom.calculator
    dimer_kwargs = {
        "calculator": calc,
        "N_raw": N_raw,
    }
    dimer = Dimer(**dimer_kwargs)
    geom.set_calculator(dimer)

    g0 = dimer.add_gaussian(geom.atoms, geom.coords, dimer.N)

    assert g0.height == pytest.approx(0.1708984)
示例#11
0
def run_dimer():
    x0 = (-0.5767, 1.6810, 0)
    geom0 = AnaPot.get_geom(x0)

    N = np.array((-0.9, 0.43, 0))
    N /= np.linalg.norm(N)
    R = 0.125
    coords = dimer_method(geom0, N, R, AnaPot, max_step=0.6, max_cycles=5)

    coords = np.array(coords)
    pot = AnaPot()
    pot.plot()
    ax = pot.ax
    for i, rot_cycle in enumerate(coords):
        ax.plot(*rot_cycle.T[:2], "o-", label=f"Cycle {i:02d}")
    ax.legend()
    plt.show()
示例#12
0
def test_line_search(line_search, ref_cycle, ref_energy):
    geom = AnaPot.get_geom((0.687, 1.57, 0.))

    opt_kwargs = {
        "thresh": "gau_tight",
        "line_search": line_search,
        "max_cycles": 64,
        "precon": False,
    }
    opt = PreconSteepestDescent(geom, **opt_kwargs)
    opt.run()

    # geom.calculator.plot_opt(opt)

    assert opt.is_converged
    assert opt.cur_cycle == ref_cycle
    assert geom.energy == pytest.approx(ref_energy)
示例#13
0
def test_line_search(line_search, ref_cycle):
    geom = AnaPot.get_geom((0.687, 1.57, 0.0))

    opt_kwargs = {
        "thresh": "gau_tight",
        "line_search": line_search,
        "max_cycles": 64,
        "precon": False,
    }
    opt = PreconLBFGS(geom, **opt_kwargs)
    opt.run()

    # geom.calculator.plot_opt(opt, show=True)

    assert opt.is_converged
    assert opt.cur_cycle == ref_cycle
    assert geom.energy == pytest.approx(0.98555442)
示例#14
0
def test_armijo(line_search, ref_cycle):
    geom = AnaPot.get_geom((0.2, 1.3, 0.0))

    opt_kwargs = {
        "thresh": "gau_tight",
        "precon": False,
        # "use_grad": use_grad,
        "line_search": line_search,
    }
    opt = PreconLBFGS(geom, **opt_kwargs)
    opt.run()

    # geom.calculator.plot_opt(opt, show=True)

    assert opt.is_converged
    assert opt.cur_cycle == ref_cycle
    assert geom.energy == pytest.approx(-0.51340926)
示例#15
0
def test_diis():
    geom = AnaPot.get_geom((0.4333, 3.14286, 0.))
    opt_kwargs = {
        # "max_step": 0.5,
        # "trust_max": 0.1,
        "thresh": "gau_tight",
        # "eins": True,
        "zwei": True,
    }
    opt = RFOptimizer(geom, **opt_kwargs)
    opt.run()
    calc = geom.calculator
    calc.plot()
    ax = calc.ax

    cs = np.array(opt.coords)
    ax.plot(*cs.T[:2], "ro-")
    plt.show()
示例#16
0
def test_pred():
    geom = AnaPot.get_geom((-0.174, 1.27, 0.))
    calc = geom.calculator
    trst = 0.05
    opt_kwargs = {
        "trust_min": trst,
        "trust_radius": trst,
        "trust_max": 0.3,
        "hessian_recalc": 1,
        "max_micro_cycles": 1,
    }
    opt = RSPRFOptimizer(geom, **opt_kwargs)
    opt.run()
    coords = np.array(opt.coords)

    calc.plot()
    ax = calc.ax
    ax.plot(*coords.T[:2], "ro-")
    plt.show()
示例#17
0
def test_anapot_cbm_rot():
    pot = AnaPot()
    geoms = (pot.get_geom((0.44, 1.54, 0)), )
    N_init = (-0.2, 1, 0)
    calc_getter = AnaPot
    dimer_kwargs = {
        "ana_2dpot": True,
        "restrict_step": "max",
        "angle_tol": 0.5,
        "f_thresh": 1e-4,
        "rot_opt": "lbfgs",
        "trans_opt": "lbfgs",
        "trans_memory": 5,
        "f_tran_mod": False,
        "N_init": N_init,
        "rot_f_thresh": 1e-2,
        # "multiple_translations": True,
    }
    result = dimer_method(geoms, calc_getter, **dimer_kwargs)
    true_ts = (0.61173, 1.49297, 0.)
    # plot_dimer_cycles(result.dimer_cycles, pot=AnaPot(), true_ts=true_ts[:2])
    return result
示例#18
0
def test_linesearch():
    geom = AnaPot.get_geom((0.667, 1.609, 0.))

    rfo_kwargs = {
        # "trust_radius": 0.75,
        "trust_radius": 0.75,
        "thresh": "gau_tight",
        # "max_cycles": 14,
        # "hessian_recalc": 3,
        # "hessian_init": "calc",
        "line_search": True,
    }
    rfo = RFOptimizer(geom, **rfo_kwargs)
    rfo.run()


    coords = np.array(rfo.coords)
    calc = geom.calculator
    calc.plot()
    ax = calc.ax
    ax.plot(*coords.T[:2], "o-")
    for i, coords in enumerate(coords):
        ax.annotate(f"{i}", coords[:2])
    plt.show()
示例#19
0
def run_dimer():
    x0 = (-0.5767, 1.6810, 0)
    geom0 = AnaPot.get_geom(x0)

    N = np.array((-0.9, 0.43, 0))
    N /= np.linalg.norm(N)
    R = 0.125

    geom1, geom2 = get_dimer_ends(geom0, N, R, AnaPot)
    coords = list()
    for i in range(35):
        f0 = geom0.forces
        norm_f0 = np.linalg.norm(f0)
        print(f"{i:0d} {norm_f0:.6f}")
        if norm_f0 < 1e-3:
            print("Converged!")
            break
        # Rotation
        rot_result = rotate_dimer(geom0, geom1, geom2, N, R)
        geom1, geom2, N, C, _ = rot_result
        # Translation
        trans_result = translate_dimer(geom0, N, C)
        update_dimer_ends(geom0, geom1, geom2, N, R)
        # Backup for plotting
        cs = (geom1.coords, geom0.coords, geom2.coords)
        coords.append(cs)

    # geom0.calculator.plot_eigenvalue_structure(grid=100)
    coords = np.array(coords)
    pot = AnaPot()
    pot.plot()
    ax = pot.ax
    for i, rot_cycle in enumerate(coords):
        ax.plot(*rot_cycle.T[:2], "o-", label=f"Cycle {i:02d}")
    ax.legend()
    plt.show()
示例#20
0
def test_velocity_verlet():
    geom = AnaPot.get_geom((0.52, 1.80, 0))
    x0 = geom.coords.copy()
    v0 = .1 * np.random.rand(*geom.coords.shape)
    t = 3
    dts = (.005, .01, .02, .04, .08)
    all_xs = list()
    for dt in dts:
        geom.coords = x0.copy()
        md_kwargs = {
            "v0": v0.copy(),
            "t": t,
            "dt": dt,
        }
        md_result = md(geom, **md_kwargs)
        all_xs.append(md_result.coords)
    calc = geom.calculator
    calc.plot()
    ax = calc.ax
    for dt, xs in zip(dts, all_xs):
        ax.plot(*xs.T[:2], "o-", label=f"dt={dt:.3f}")
        # ax.plot(*xs.T[:2], "-", label=f"dt={dt:.3f}")
    ax.legend()
    plt.show()
示例#21
0
def test_sd_gediis():
    geom = AnaPot.get_geom((0.4333, 3.14286, 0.))

    trust = 0.3
    H = np.eye(geom.coords.size)

    ens = list()
    cs = list()
    dcs = list()
    fs = list()
    pairs = list()
    for i in range(25):
        forces = geom.forces
        energy = geom.energy

        cs.append(geom.coords)
        fs.append(forces)
        ens.append(energy)

        forces_norm = np.linalg.norm(forces)
        print(f"{i:02d}: {forces_norm:.6f}")
        if forces_norm < 1e-3:
            print("Converged!")
            break

        # Calculate reference step
        step = get_step(H, forces, trust)

        if len(fs) > 1:
            gediis_res = gediis(cs, ens, fs)

            if gediis_res is not None:
                # Inter-/extrapolate coordinates and forces
                coords_ = gediis_res.coords
                forces = gediis_res.forces
                dcs.append(coords_)
                geom.coords = coords_
                forces_norm = np.linalg.norm(forces)
                # Get new step from GEDIIS coordinates & forces
                step = get_step(H, forces, trust)

        new_coords = geom.coords + step
        geom.coords = new_coords

    cs = np.array(cs)
    dcs = np.array(dcs)
    calc = geom.calculator
    calc.plot()
    ax = calc.ax
    ax.plot(*cs.T[:2], "o-")
    for i, cs_ in enumerate(cs):
        ax.annotate(f"{i:02d}", cs_[:2])

    ax.plot(*dcs.T[:2], "o-")
    for oc, dc, rs in pairs:
        line = mlines.Line2D((oc[0], dc[0]), (oc[1], dc[1]),
                             ls="--",
                             color="k")
        ax.add_artist(line)
        line = mlines.Line2D((oc[0], rs[0]), (oc[1], rs[1]),
                             ls="--",
                             color="r")
        ax.add_artist(line)
    plt.show()
示例#22
0
def run():
    geom = AnaPot.get_geom((-1, 3, 0))
    print(geom)

    def prep_post(geom):
        return {
            "coords": geom.coords.tolist(),
            "gradient": geom.gradient.tolist(),
            "energy": float(geom.energy),
        }

    req_kwargs = {
        "headers": {
            "Content-type": "application/json",
        },
    }
    base_url = "http://localhost:8080/"

    def send_json(path, data):
        url = base_url + path
        response = requests.post(url=url, data=json.dumps(data), **req_kwargs)
        return response

    init = {
        "key": "cg",
        "alpha": 0.1,
        "gdiis": False,
        "line_search": False,
    }
    init_resp = send_json("init", init)
    print("Init response", init_resp)

    coords = list()
    opt_state = OptState(alpha=0.3, key="cg")

    for i in range(50):
        coords.append(geom.coords)
        print("\tcur. coords", geom.coords)
        gradient = geom.gradient
        norm = np.linalg.norm(gradient)

        print(f"{i:02d}: norm(grad)={norm:.6f}")
        if norm <= 0.1:
            print("Converged")
            break

        pp = prep_post(geom)
        # # resp = requests.post(**req_kwargs, data=pp)
        # resp = send_json("step", pp)
        # resp_data = resp.json()

        # step = resp_data["step"]
        # status = resp_data["status"]
        step, status = opt_state.step(geom.coords, geom.energy, geom.gradient)
        new_coords = geom.coords + step
        # print("\t", status)
        geom.coords = new_coords
        print()
        print()

        # import pdb; pdb.set_trace()
        # pass

    coords = np.array(coords)
    calc = geom.calculator
    calc.plot()
    ax = calc.ax
    ax.plot(*coords.T[:2], "ro-")
    for i, xy in enumerate(coords[:, :2]):
        ax.annotate(str(i), xy)
    plt.show()
示例#23
0
def get_geoms():
    initial = AnaPot.get_geom((-1.05274, 1.02776, 0))
    final = AnaPot.get_geom((1.94101, 3.85427, 0))
    geoms = (initial, final)
    return geoms
示例#24
0
def test_sd_gdiis():
    geom = AnaPot.get_geom((0.4333, 3.14286, 0.))

    trust = 0.3
    H = np.eye(geom.coords.size)

    cs = list()
    dcs = list()
    fs = list()
    pairs = list()
    for i in range(50):
        forces = geom.forces

        cs.append(geom.coords)
        fs.append(forces)

        forces_norm = np.linalg.norm(forces)
        print(f"{i:02d}: {forces_norm:.6f}")
        if forces_norm < 1e-3:
            print("Converged!")
            break

        # Calculate reference step
        step = get_step(H, forces, trust)

        if len(fs) > 1:
            gdiis_kwargs = {
                "coords": cs,
                "forces": fs,
                "ref_step": step,
            }
            res = gdiis(fs, **gdiis_kwargs)
            if res:
                # Inter-/extrapolate coordinates and forces
                coords_ = res.coords
                forces = res.forces
                dcs.append(coords_)
                pairs.append((geom.coords.copy(), coords_, geom.coords + step))
                geom.coords = coords_
                forces_norm = np.linalg.norm(forces)
                # Get new step from DIIS coordinates & forces
                step = get_step(H, forces, trust)

        new_coords = geom.coords + step
        geom.coords = new_coords
    # return

    cs = np.array(cs)
    dcs = np.array(dcs)
    calc = geom.calculator
    calc.plot()
    ax = calc.ax
    ax.plot(*cs.T[:2], "o-")
    for i, cs_ in enumerate(cs):
        ax.annotate(f"{i:02d}", cs_[:2])

    ax.plot(*dcs.T[:2], "o-")
    for oc, dc, rs in pairs:
        line = mlines.Line2D((oc[0], dc[0]), (oc[1], dc[1]),
                             ls="--",
                             color="k")
        ax.add_artist(line)
        line = mlines.Line2D((oc[0], rs[0]), (oc[1], rs[1]),
                             ls="--",
                             color="r")
        ax.add_artist(line)
    plt.show()
示例#25
0
def test_dwi():
    dwi = DWI()

    coords = np.array((
        (-0.222, 1.413, 0.),
        (-0.812, 1.242, 0.),
    ))
    geom = AnaPot.get_geom(coords[0])
    calc = geom.calculator

    c1 = geom.coords
    e1 = geom.energy
    g1 = geom.gradient
    h1 = geom.hessian
    dwi.update(c1, e1, g1, h1)

    geom.coords = coords[1]
    c2 = geom.coords
    e2 = geom.energy
    g2 = geom.gradient
    h2 = geom.hessian
    dwi.update(c2, e2, g2, h2)

    points = 10
    step = (coords[1] - coords[0]) / (points - 1)
    true_ens = list()
    true_grads = list()
    interpol_ens = list()
    interpol_grads = list()
    findiff = 1e-4
    fd_grads = list()
    for i in range(points):
        new_coords = coords[0] + i * step
        geom.coords = new_coords
        true_grad = geom.gradient
        true_grads.append(true_grad)
        true_energy = geom.energy
        true_ens.append(true_energy)
        interpol_energy, interpol_grad = dwi.interpolate(new_coords,
                                                         gradient=True)
        interpol_ens.append(interpol_energy)
        interpol_grads.append(interpol_grad)

        fd_grad = list()
        for i in range(3):
            fd_step = np.zeros(3)
            fd_step[i] = findiff
            plus_val = dwi.interpolate(new_coords + fd_step)
            minus_val = dwi.interpolate(new_coords - fd_step)
            fd = (plus_val - minus_val) / (2 * findiff)
            fd_grad.append(fd)
        fd_grads.append(fd_grad)

    true_ens = np.array(true_ens)
    interpol_ens = np.array(interpol_ens)
    true_grads = np.array(true_grads)
    interpol_grads = np.array(interpol_grads)
    fd_grads = np.array(fd_grads)
    np.testing.assert_allclose(interpol_grads, fd_grads)

    quiver_xs = np.arange(interpol_ens.size)
    quiver_true_ys = true_ens
    quiver_interpol_ys = interpol_ens
    fig, ax = plt.subplots()
    ax.plot(true_ens, label="True")
    ax.plot(interpol_ens, label="DWI")

    tg_U = true_grads[:, 0]
    tg_V = true_grads[:, 1]
    ti_U = interpol_grads[:, 0]
    ti_V = interpol_grads[:, 1]
    ax.quiver(quiver_xs,
              quiver_true_ys,
              tg_U,
              tg_V,
              color="b",
              label="grad(True)")
    ax.quiver(quiver_xs,
              quiver_interpol_ys,
              ti_U,
              ti_V,
              color="orange",
              label="grad(DWI)")
    ax.legend()

    plt.show()
示例#26
0
def test_euler():
    dwi = DWI()

    coords = np.array((
        (-0.222, 1.413, 0.),
        (-0.812, 1.242, 0.),
    ))
    # Half step
    # diff = coords[1] - coords[0]
    # coords[1] = coords[0] + 0.5*diff
    geom = AnaPot.get_geom(coords[0])
    calc = geom.calculator

    c1 = geom.coords
    e1 = geom.energy
    g1 = geom.gradient
    h1 = geom.hessian
    dwi.update(c1, e1, g1, h1)

    geom.coords = coords[1]
    c2 = geom.coords
    e2 = geom.energy
    g2 = geom.gradient
    h2 = geom.hessian
    dwi.update(c2, e2, g2, h2)

    # Euler integration
    norm = np.linalg.norm(coords[1] - coords[0])
    print(f"             norm={norm:.8f}")
    all_coords = list()
    richardson = dict()
    errors = list()
    for k in range(10):
        points = 10 * (2**k) + 1
        corr_step_length = norm / (points - 1)
        # print("corr_step_length", corr_step_length)
        cur_coords = coords[0].copy()
        k_coords = list()
        length = 0
        while True:
            k_coords.append(cur_coords.copy())
            if length >= norm:
                # print(f"Converged! length={length:.8f}, length-step={length-corr_step_length:.8f}")
                print(f"Converged! length={length:.8f}")
                break
            energy, gradient = dwi.interpolate(cur_coords, gradient=True)
            cur_coords += corr_step_length * -gradient / np.linalg.norm(
                gradient)
            length += corr_step_length
            # Check for oscillation
            try:
                prev_coords = k_coords[-2]
                osc_norm = np.linalg.norm(cur_coords - prev_coords)
                if osc_norm <= corr_step_length:
                    print("Detected oscillation. Breaking!")
                    # TODO: handle this by restarting everyhting with a smaller stepsize.
                    # Check 10.1039/c7cp03722h SI
                    assert False, "This case is not yet handled"
                    break
            except IndexError:
                pass
        richardson[(k, 0)] = cur_coords

        # Refine using Richardson extrapolation
        # Set additional values using Richard extrapolation
        for j in range(1, k + 1):
            print(f"k={k},j={j}")
            richardson[(k, j)] = ((2**j) * richardson[(k, j-1)] - richardson[(k-1, j-1)]) \
                                 / (2**j-1)
        if k > 0:
            # RMS of coordinates
            error = np.sqrt(
                np.mean((richardson[(k, k)] - richardson[(k - 1, k - 1)])**2))
            print(f"\terror={error:.8e}")
            errors.append(error)
            if error <= 1e-6:
                break
        all_coords.append(np.array(k_coords))

    print("Richardson table")
    pprint(richardson)
    print()
    print("Errors")
    erros = np.array(errors)
    print(errors)

    calc = geom.calculator
    calc.plot()
    ax = calc.ax
    ax.plot(*coords.T[:2], "r-")

    for i, ac in enumerate(all_coords, 1):
        ax.plot(*ac.T[:2], label=i)
    ax.legend()
    plt.show()
示例#27
0
def test_bias_translation():
    # coords = (-1.05, 1.02, 0)
    coords = (-1.009, 1.024, 0)
    geom = AnaPot.get_geom(coords)
    N_raw = np.array((0.9603, 0.2789, 0.))

    calc = geom.calculator
    # calc.plot_eigenvalue_structure()
    dimer_kwargs = {
        "calculator": calc,
        "N_raw": N_raw,
        "rotation_disable": True,
        # "rotation_method": "direct",
        # "bias_rotation": True,
        "bias_translation": True,
        # "bias_gaussian_dot": 0.5,
    }
    dimer = Dimer(**dimer_kwargs)
    geom.set_calculator(dimer)

    import matplotlib.pyplot as plt

    def plot(dimer, coords0, title=None, step_norms=None):
        if step_norms is None:
            step_norms = list()
            step_norms_max = 0.5
        else:
            step_norms_max = max(step_norms)

        N = dimer.N
        # steps = np.linspace(-0.025, 0.125, 30)
        steps = np.linspace(-0.05, max(step_norms_max, 0.1), 50)
        stepsN = steps[:, None] * N
        Ncoords = coords0 + steps[:, None] * N
        results = [dimer.get_forces(geom.atoms, coords) for coords in Ncoords]
        ens, forces = zip(*[(r["energy"], r["forces"]) for r in results])
        forces = np.array(forces)
        norms = np.linalg.norm(forces, axis=1)
        step1_norm = np.linalg.norm(
            np.array((-0.759042, 1.09659, 0.) - coords0))
        # fig, (ax0, ax1) = plt.subplots(nrows=2)
        fig, (ax0, ax1, ax2) = plt.subplots(nrows=3)
        ax0.plot(steps, ens)
        ax0.set_title("energy")
        ax1.plot(steps, norms, "o-")
        ax1.set_title("norm(forces)")
        # ax2.plot(*forces.T[:2], "o-")
        # for i, f in enumerate(forces):
        # ax2.annotate(i, f[:2])

        # ax2.quiver(Ncoords.[::2]
        # ax2.quiver(Ncoords[:,0], Ncoords[:,1], forces[:,0], forces[:,1])
        ax2.quiver(stepsN[:, 0],
                   stepsN[:, 1],
                   forces[:, 0],
                   forces[:, 1],
                   scale=10)
        ax2.axvline(0.0529)

        for ax in (ax0, ax1):
            ax.axvline(0, color="r", ls="--")

        for i, x in enumerate(step_norms):
            for ax in (ax0, ax1):
                ax.axvline(x, color="k", ls="--")
                mi, ma = ax.get_ylim()
                y = (mi + ma) / 2
                ax.annotate(i, (x, y))
        if title:
            fig.suptitle(title)
        return fig

    coords0 = geom.coords.copy()
    # f_ub = plot(dimer, coords0, "unbiased")

    g0 = dimer.add_gaussian(geom.atoms, geom.coords, dimer.N)
    print(g0)
    # f_b = plot(dimer, coords0, "biased")
    plt.show()
    # return

    opt_kwargs = {
        "precon": False,
        # "max_step_element": 0.06,
        # "max_step_element": 0.03,
        "max_step_element": 0.0529,
        # "max_cycles": 9,
        "max_cycles": 10,
        "dump": True,
    }
    # opt = PreconLBFGS(geom, **opt_kwargs)
    from pysisyphus.optimizers.PreconSteepestDescent import PreconSteepestDescent
    opt = PreconSteepestDescent(geom, **opt_kwargs)
    opt.run()

    step_norms = np.linalg.norm([c - coords0 for c in opt.coords], axis=1)
    f_b = plot(dimer, coords0, "biased", step_norms)
    print(step_norms)
    for i, step in enumerate(opt.steps):
        print(i, step)
    # calc.plot_opt(opt)
    plt.show()