Algorithm for finding the dimensions of connected subunits in a crystal structure.
    This method finds the dimensionality of the material even when the material is not layered along low-index planes, or does not have flat layers/molecular wires.
    See details at : Cheon, G.; Duerloo, K.-A. N.; Sendek, A. D.; Porter, C.; Chen, Y.; Reed, E. J. Data Mining for New Two- and One-Dimensional Weakly Bonded Solids and Lattice-Commensurate Heterostructures. Nano Lett. 2017.

    Args:
        structure (Structure): Input structure
        tolerance: length in angstroms used in finding bonded atoms. Two atoms are considered bonded if (radius of atom 1) + (radius of atom 2) + (tolerance) < (distance between atoms 1 and 2). Default value = 0.45, the value used by JMol and Cheon et al.
        ldict: dictionary of bond lengths used in finding bonded atoms. Values from JMol are used as default
        standardize: works with conventional standard structures if True. It is recommended to keep this as True.

    Returns:
        dim: dimension of the largest cluster as a string. If there are ions or molecules it returns 'intercalated ion/molecule'

def find_dimension(structure_raw, tolerance=0.45, ldict=JmolNN().el_radius, standardize=True):
    """
    Algorithm for finding the dimensions of connected subunits in a crystal structure.
    This method finds the dimensionality of the material even when the material is not layered along low-index planes, or does not have flat layers/molecular wires.
    See details at : Cheon, G.; Duerloo, K.-A. N.; Sendek, A. D.; Porter, C.; Chen, Y.; Reed, E. J. Data Mining for New Two- and One-Dimensional Weakly Bonded Solids and Lattice-Commensurate Heterostructures. Nano Lett. 2017.

    Args:
        structure (Structure): Input structure
        tolerance: length in angstroms used in finding bonded atoms. Two atoms are considered bonded if (radius of atom 1) + (radius of atom 2) + (tolerance) < (distance between atoms 1 and 2). Default value = 0.45, the value used by JMol and Cheon et al.
        ldict: dictionary of bond lengths used in finding bonded atoms. Values from JMol are used as default
        standardize: works with conventional standard structures if True. It is recommended to keep this as True.

    Returns:
        dim: dimension of the largest cluster as a string. If there are ions or molecules it returns 'intercalated ion/molecule'
    """
    if standardize:
        structure = SpacegroupAnalyzer(structure_raw).get_conventional_standard_structure()
    structure_save = copy.copy(structure_raw)
    connected_list1 = find_connected_atoms(structure, tolerance=tolerance, ldict=ldict)
    max1, min1, clusters1 = find_clusters(structure, connected_list1)
    structure.make_supercell([[2, 0, 0], [0, 2, 0], [0, 0, 2]])
    connected_list2 = find_connected_atoms(structure, tolerance=tolerance, ldict=ldict)
    max2, min2, clusters2 = find_clusters(structure, connected_list2)
    if min2 == 1:
        dim = 'intercalated ion'
    elif min2 == min1:
        if max2 == max1:
            dim = '0D'
        else:
            dim = 'intercalated molecule'
    else:
        dim = np.log2(float(max2) / max1)
        if dim == int(dim):
            dim = str(int(dim)) + 'D'
        else:
            structure=copy.copy(structure_save)
            structure.make_supercell([[3, 0, 0], [0, 3, 0], [0, 0, 3]])
            connected_list3 = find_connected_atoms(structure, tolerance=tolerance, ldict=ldict)
            max3, min3, clusters3 = find_clusters(structure, connected_list3)
            if min3 == min2:
                if max3 == max2:
                    dim = '0D'
                else:
                    dim = 'intercalated molecule'
            else:
                dim = np.log2(float(max3) / max1) / np.log2(3)
                if dim == int(dim):
                    dim = str(int(dim)) + 'D'
                else:
                    return
    return dim