Reads an unstructured mesh with added data.

    :param filenames: The files to read from.
    :type filenames: str

    :returns mesh{2,3}d: The mesh data.

def read(filename, file_format=None):
    """Reads an unstructured mesh with added data.

    :param filenames: The files to read from.
    :type filenames: str

    :returns mesh{2,3}d: The mesh data.
    """
    # https://stackoverflow.com/q/4843173/353337
    assert isinstance(filename, str)

    if not file_format:
        # deduce file format from extension
        file_format = _filetype_from_filename(filename)

    format_to_reader = {
        "ansys": ansys_io,
        "ansys-ascii": ansys_io,
        "ansys-binary": ansys_io,
        #
        "gmsh": msh_io,
        "gmsh-ascii": msh_io,
        "gmsh-binary": msh_io,
        "gmsh2": msh_io,
        "gmsh2-ascii": msh_io,
        "gmsh2-binary": msh_io,
        "gmsh4": msh_io,
        "gmsh4-ascii": msh_io,
        "gmsh4-binary": msh_io,
        #
        "med": med_io,
        "medit": medit_io,
        "dolfin-xml": dolfin_io,
        "permas": permas_io,
        "moab": h5m_io,
        "off": off_io,
        #
        "stl": stl_io,
        "stl-ascii": stl_io,
        "stl-binary": stl_io,
        #
        "vtu-ascii": vtu_io,
        "vtu-binary": vtu_io,
        #
        "vtk-ascii": vtk_io,
        "vtk-binary": vtk_io,
        #
        "xdmf": xdmf_io,
        "exodus": exodus_io,
        #
        "abaqus": abaqus_io,
        #
        "mdpa": mdpa_io,
    }

    assert file_format in format_to_reader, "Unknown file format '{}' of '{}'.".format(
        file_format, filename
    )

    return format_to_reader[file_format].read(filename)