Пример #1
0
    def test_same_minima_Frenkel(self):
        nparticles = 32
        hs_radii = 0.05 * np.random.randn(nparticles) + 1
        volpart = np.sum(4. / 3. * np.pi * hs_radii**3)
        phi = 0.7
        boxl = (volpart / phi)**(1 / 3.)
        boxv = [boxl, boxl, boxl]
        coords = np.random.rand(nparticles * 3) * boxl
        ncellx_scale = get_ncellsx_scale(np.ones(nparticles), boxv)
        pot_cellists = Frenkel(boxvec=boxv,
                               celllists=True,
                               ncellx_scale=ncellx_scale)
        pot_no_cellists = Frenkel(boxvec=boxv,
                                  celllists=False,
                                  ncellx_scale=ncellx_scale)
        nsteps = 1000
        tol = 1e-5
        res_cell_lists = lbfgs_cpp(coords,
                                   pot_cellists,
                                   nsteps=nsteps,
                                   tol=tol)
        res_no_cell_lists = lbfgs_cpp(coords,
                                      pot_no_cellists,
                                      nsteps=nsteps,
                                      tol=tol)

        fcoords_cell_lists = res_cell_lists.coords
        fcoords_no_cell_lists = res_no_cell_lists.coords
        # self.assertEqual(fcoords_no_cell_lists,fcoords_cell_lists)
        self.assertTrue(np.all(fcoords_no_cell_lists == fcoords_cell_lists))
Пример #2
0
def generate_save_secondary_params(par, folder):
    """ 
    TODO: rename to reflect this is for a binary system
    Generates a list of secondary parameters hs_radii,
    boxlength and scale and initial coords and saves them to the folder
    """
    np.random.seed(0)
    # hs_radii = (par.radius_std.value *
    #             np.random.randn(par.n_part.value)
    #             + par.radius_mean.value)

    # for binary mixture
    npart_by_2 = par.n_part.value // 2
    # NOTE: TODO: bug fix seeds
    hs_radii = np.array(
        list(par.r1.value + par.rstd1.value * np.random.randn(npart_by_2)) +
        list(par.r2.value +
             par.rstd2.value * np.random.randn(par.n_part.value - npart_by_2)))
    print(hs_radii, "hs_radii")
    print(len(hs_radii), "nparts")
    box_length = get_box_length(hs_radii, par.ndim.value, par.phi.value)
    print(box_length, "box_length")
    # initial coords are present, to keep continuity with previous code. but they are not necessary
    initial_coords = np.random.rand(
        par.n_part.value * par.ndim.value) * box_length
    print(initial_coords, "initial coords")
    print(get_ncellsx_scale(hs_radii, [box_length, box_length, box_length]),
          "cell scale")
    print(len(initial_coords), "initial_coords length")
    np.savetxt(folder + "/hs_radii.txt", hs_radii, delimiter=",")
    np.savetxt(folder + "/initial_coords.txt", initial_coords, delimiter=",")
    np.savetxt(folder + "/box_length.txt", [box_length], delimiter=",")
Пример #3
0
def generate_save_run_params_ip_binary(par, folder, seed=0):
    """ Generates and saves the run parameters.
        Creates a new folder called sec_params if it does not exist and a subfolder defined by the seed

    Parameters
    ----------
    par : SystemParamInversePowerBinary
        System defining the parameters
    folder : str
        Folder defining our system
    seed : int, optional
        seed for generating random parameters
    """
    np.random.seed(seed)

    # for binary mixture
    npart_by_2 = par.n_part.value // 2
    hs_radii = np.array(
        list(par.r1.value + par.rstd1.value * np.random.randn(npart_by_2)) +
        list(par.r2.value +
             par.rstd2.value * np.random.randn(par.n_part.value - npart_by_2)))
    print(hs_radii, "hs_radii")
    print(len(hs_radii), "nparts")
    box_length = get_box_length(hs_radii, par.ndim.value, par.phi.value)
    print(box_length, "box_length")
    # initial coords are present, to keep continuity with previous code. but they are not necessary
    initial_coords = np.random.rand(
        par.n_part.value * par.ndim.value) * box_length
    print(initial_coords, "initial coords")
    print(get_ncellsx_scale(hs_radii, [box_length, box_length, box_length]),
          "cell scale")
    print(len(initial_coords), "initial_coords length")
    os.makedirs(folder + "/" + "sec_params" + "/" + str(seed), exist_ok=True)
    np.savetxt(
        folder + "/" + "sec_params" + "/" + str(seed) + "/hs_radii.txt",
        hs_radii,
        delimiter=",",
    )
    np.savetxt(
        folder + "/" + "sec_params" + "/" + str(seed) + "/initial_coords.txt",
        initial_coords,
        delimiter=",",
    )
    np.savetxt(
        folder + "/" + "sec_params" + "/" + str(seed) + "/box_length.txt",
        [box_length],
        delimiter=",",
    )
Пример #4
0
    def test_same_minima_HS_WCA(self):
        nparticles = 32
        radius_sca = 0.9085602964160698
        pot_sca = 0.1
        eps = 1.0
        hs_radii = 0.05 * np.random.randn(nparticles) + 1
        volpart = np.sum(4. / 3. * np.pi * hs_radii**3)
        phi = 0.7
        boxl = (volpart / phi)**(1 / 3.)
        boxv = [boxl, boxl, boxl]
        coords = np.random.rand(nparticles * 3) * boxl
        ncellx_scale = get_ncellsx_scale(np.ones(nparticles), boxv)
        bdim = 3
        distance_method = Distance.PERIODIC
        pot_cellists = HS_WCA(use_cell_lists=True,
                              eps=eps,
                              sca=pot_sca,
                              radii=hs_radii * radius_sca,
                              boxvec=boxv,
                              ndim=bdim,
                              ncellx_scale=ncellx_scale,
                              distance_method=distance_method)
        pot_no_cellists = HS_WCA(use_cell_lists=False,
                                 eps=eps,
                                 sca=pot_sca,
                                 radii=hs_radii * radius_sca,
                                 boxvec=boxv,
                                 ndim=bdim,
                                 ncellx_scale=ncellx_scale,
                                 distance_method=distance_method)
        nsteps = 1000
        tol = 1e-5
        res_cell_lists = lbfgs_cpp(coords,
                                   pot_cellists,
                                   nsteps=nsteps,
                                   tol=tol)
        res_no_cell_lists = lbfgs_cpp(coords,
                                      pot_no_cellists,
                                      nsteps=nsteps,
                                      tol=tol)

        fcoords_cell_lists = res_cell_lists.coords
        fcoords_no_cell_lists = res_no_cell_lists.coords
        # self.assertEqual(fcoords_no_cell_lists,fcoords_cell_lists)
        self.assertTrue(np.all(fcoords_no_cell_lists == fcoords_cell_lists))
def map_binary_inversepower(
    foldername,
    particle_coords,
    optimizer,
    parameter_dict,
    random_coord_0=0,
    random_coord_1=-1,
    z=0,
):
    """
    Finds whether a point defined by particle_coord
    on the meshgrid correspond to a minimum or not for a 2d
    case.
    """
    foldpath = BASE_DIRECTORY + "/" + foldername
    # import params
    sysparams = load_params(foldpath)
    (hs_radii, initial_coords, box_length) = load_secondary_params(foldpath)
    assert sysparams.ndim.value == 2
    minimum_coords = np.loadtxt(foldpath + "/coords_of_minimum.txt", delimiter=",")
    quench_coords = initial_coords.copy()

    if len(quench_coords) == 16:
        quench_coords = (
            quench_coords
            + particle_coords[0] * VEC_8_0
            + particle_coords[1] * VEC_8_1
            + z * VEC_8_2
        )
    elif len(quench_coords) == 32:
        quench_coords = (
            quench_coords
            + particle_coords[0] * VEC_16_0
            + particle_coords[1] * VEC_16_1
            + z * VEC_16_2
        )
    elif len(quench_coords) == 64:
        quench_coords = (
            quench_coords
            + particle_coords[0] * VEC_16_0
            + particle_coords[1] * VEC_16_1
            + z * VEC_16_2
        )
    else:
        raise Exception("error other random coords have not been generated")

    print(quench_coords, "quench")
    # print(quench_coords, 'quench coords')
    # box length
    box_length = float(box_length)
    boxv = [box_length] * sysparams.ndim.value
    ncellx_scale = get_ncellsx_scale(hs_radii, boxv)
    potential = InversePower(
        sysparams.power.value,
        sysparams.eps.value,
        use_cell_lists=False,
        ndim=sysparams.ndim.value,
        radii=hs_radii * 1.0,
        boxvec=boxv,
    )

    # ret = quench_mixed_optimizer(potential,
    #                              quench_coords,  # make sure right coords are being passed
    #                              T=10,
    #                              step=1,
    #                              nsteps=100000,
    #                              conv_tol=1e-8,
    #                              tol=1e-6, rtol=1e-4, atol=1e-4)
    # ret = quench_steepest(
    #     potential,
    #     quench_coords,  # make sure right coords are being passed
    #     nsteps=2000000,
    #     stepsize=5e-3,  # for steepest descent step size should be small
    #     tol=1e-4)
    # ret = quench_cvode_opt(potential, quench_coords, tol=1e-6, rtol=1e-4, atol=1e-4)
    try:
        ret = optimizer(quench_coords, potential, **parameter_dict)
    except:
        print(quench_coords, "failed here")
        print(initial_coords, "coords")
        print(len(quench_coords))
        raise Exception("failure")

    # ret = lbfgs_cpp(quench_coords, potential, tol=1e-8, M=1)

    # This exists because some runs don't have hessian evaluations
    try:
        ret["nhev"]
    except:
        ret["nhev"] = 0
    coordarg = 0
    results = (ret.coords, ret.success, coordarg, ret.nfev, ret.nsteps, ret.nhev)
    # the reason the potential is being passed is because quench coords needs the potential to figure out what to do
    return results
Пример #6
0
def map_binary_inversepower(
    foldername,
    particle_coords,
    optimizer,
    parameter_dict,
    random_coord_0=0,
    random_coord_1=-1,
    z=0,
    index=None,
    mesh_length=None,
):
    """
    Finds whether a point defined by particle_coord
    on the meshgrid correspond to a minimum or not for a 2d
    case.
    """
    foldpath = BASE_DIRECTORY + "/" + foldername
    # import params
    sysparams = load_params(foldpath)
    (hs_radii, initial_coords, box_length) = load_secondary_params(foldpath)
    assert sysparams.ndim.value == 2
    quench_coords = initial_coords.copy()
    print("initial_coords", initial_coords)

    print(particle_coords[0], particle_coords[1],
          "vector coefficients as passed")
    print("z value")
    quench_coords = (quench_coords + particle_coords[0] * VEC_16_0 +
                     particle_coords[1] * VEC_16_1 + z * VEC_16_2)

    # TODO: save this as a unit meshgrid
    # print(quench_coords, 'quench coords')
    # box length
    box_length = float(box_length)
    boxv = [box_length] * sysparams.ndim.value
    ncellx_scale = get_ncellsx_scale(hs_radii, boxv)
    print(hs_radii)
    potential = InversePower(
        sysparams.power.value,
        sysparams.eps.value,
        use_cell_lists=False,
        ndim=sysparams.ndim.value,
        radii=hs_radii * 1.0,
        boxvec=boxv,
    )
    # save potential parameters
    # writing this out since Enum to dict conversion does not give the mapping we want
    potential_params_fname = "potential_params.yaml"
    potential_param_dict = {
        "ndim": sysparams.ndim.value,
        "phi": sysparams.phi.value,
        "seed": 0,
        "n_part": sysparams.n_part.value,
        "r1": sysparams.r1.value,
        "r2": sysparams.r2.value,
        "rstd1": sysparams.rstd1.value,
        "rstd2": sysparams.rstd2.value,
        "use_cell_lists": int(False),
        "power": sysparams.power.value,
        "eps": sysparams.eps.value,
    }

    param_str = generate_param_str_from_dict(potential_param_dict)

    # make directory to emulate structure by refactored code
    emulation_folder = COMPARE_FOLDER_NAME + "/" + param_str
    # add README to emulation folder
    os.makedirs(emulation_folder, exist_ok=True)
    with open(COMPARE_FOLDER_NAME + "/README.org", "w") as f:
        f.write(" \#+AUTHOR Praharsh Suryadevara .\n")
        f.write("* Read First.")
        f.write(
            "This dirctory has been auto-generated by old code before refactoring. Do not change.\n"
        )

    # emulates path of the refactored code
    ensemble_folder_path = emulation_folder + "/ensemble/random_plane"
    os.makedirs(ensemble_folder_path, exist_ok=True)

    # 0 to emulate the addition of seed
    sec_param_folder_path = emulation_folder + "/sec_params/0"
    os.makedirs(sec_param_folder_path, exist_ok=True)

    old_code_results_folder_path = emulation_folder + "/old_data"
    os.makedirs(old_code_results_folder_path, exist_ok=True)

    with open(emulation_folder + "/params.yaml", "w") as param_file:
        yaml.dump(potential_param_dict, param_file)

    opt_param_fname = "minima_finder_params.yaml"
    with open(emulation_folder + "/" + opt_param_fname, "w") as param_file:
        yaml.dump(parameter_dict, param_file)

    initial_coords_fname = str(index) + ".txt"
    np.savetxt(ensemble_folder_path + "/" + initial_coords_fname,
               quench_coords,
               delimiter=",")

    mesh_coords_fname = str(index) + "_mesh.txt"
    np.savetxt(ensemble_folder_path + "/" + mesh_coords_fname,
               particle_coords,
               delimiter=",")

    if mesh_length is not None:
        # 2 *[particle_coords[0], particle_coords[1]]/mesh_length -0.5 form our unit mesh_grid
        # centered around [0, 0]
        mesh_coords = (2 * np.array([particle_coords[0], particle_coords[1]]) /
                       mesh_length - 0.5)
        mesh_coords_fname = str(index) + "_mesh.txt"
        np.savetxt(ensemble_folder_path + "/" + mesh_coords_fname,
                   mesh_coords,
                   delimiter=",")

    np.savetxt(
        sec_param_folder_path + "/" + "initial_coords.txt",
        initial_coords,
        delimiter=",",
    )
    np.savetxt(
        sec_param_folder_path + "/" + "box_length.txt",
        np.array([box_length]),
        delimiter=",",
    )
    np.savetxt(sec_param_folder_path + "/" + "hs_radii.txt",
               hs_radii,
               delimiter=",")

    # ret = quench_mixed_optimizer(potential,
    #                              quench_coords,  # make sure right coords are being passed
    #                              T=10,
    #                              step=1,
    #                              nsteps=100000,
    #                              conv_tol=1e-8,
    #                              tol=1e-6, rtol=1e-4, atol=1e-4)
    # ret = quench_steepest(
    #     potential,
    #     quench_coords,  # make sure right coords are being passed
    #     nsteps=2000000,
    #     stepsize=5e-3,  # for steepest descent step size should be small
    #     tol=1e-4)
    # ret = quench_cvode_opt(potential, quench_coords, tol=1e-6, rtol=1e-4, atol=1e-4)
    try:
        ret = optimizer(quench_coords, potential, **parameter_dict)
    except:
        raise Exception("failure")
    # ret = lbfgs_cpp(quench_coords, potential, tol=1e-8, M=1)

    # This exists because some runs don't have hessian evaluations
    try:
        ret["nhev"]
    except:
        ret["nhev"] = 0
    coordarg = 0

    final_coords = ret["coords"]
    final_coords_fname = str(index) + "_coords.txt"
    np.savetxt(
        old_code_results_folder_path + "/" + final_coords_fname,
        final_coords,
        delimiter=",",
    )

    energy, grad, hess = potential.getEnergyGradientHessian(final_coords)

    hessian_fname = str(index) + "_hessian.txt"
    np.savetxt(old_code_results_folder_path + "/" + hessian_fname,
               hess,
               delimiter=",")
    grad_fname = str(index) + "_grad.txt"
    np.savetxt(old_code_results_folder_path + "/" + grad_fname,
               grad,
               delimiter=",")

    last_step_fname = str(index) + "_step.txt"
    # np.savetxt(old_code_results_folder_path + '/' +
    #            last_step_fname, ret['step'], delimiter=',')

    # check that the minimum hessian eigenvalue is positive
    # print out the eigenvector corresponding to it
    eigvals, eigvecs = np.linalg.eigh(hess)
    print(eigvals[1])
    print(eigvecs[:, 1])

    # step_in_eigvec_basis = np.matmul(eigvecs.T, ret['step'])
    # step_in_eigvec_basis_normalized = step_in_eigvec_basis/np.linalg.norm(step_in_eigvec_basis)

    # -1e-15 is to avoid numerical issues
    if np.min(eigvals) < -1e-3:
        print("minimum Eigenvalue: ", np.min(eigvals))
        print("Eigenvalues: ", eigvals)
        raise Exception("negative eigenvalue")

    # save heuristics as a dict
    results = (
        ret.coords,
        ret.success,
        coordarg,
        ret.nfev,
        ret.nsteps,
        ret.nhev,
        eigvecs,
    )

    # simplified dictionary since we're only using the success variable
    res_dict = {
        "success": bool(ret.success),
        "nsteps": ret.nsteps,
        "energy": ret.energy,
        "nfev": ret.nfev,
    }
    # print("-------------------------------------------------steppp", step_in_eigvec_basis_normalized)
    # print("eigenvalues", eigvals)

    yaml_fname = str(index) + ".yaml"
    # save heuristics as yaml
    with open(old_code_results_folder_path + "/" + yaml_fname, "w") as f:
        yaml.dump(res_dict, f)

    print(ret.nsteps, "nsteps")
    # the reason the potential is being passed is because quench coords needs the potential to figure out what to do
    return results