//  [python]
def _calc_u_intensities_dd(
    u_fluxes,
    E_th_i,
    primary_model,
    interaction_model,
    atmosphere,
    location,
    month,
    output,
    file_name,
    force,
):

    """This function calculates double-differential underground intensities for mountain overburdens."""

    # Check values

    constants._check_constants()

    if constants.get_overburden() != "mountain":

        raise ValueError(
            "Double-differential underground intensities can only be calculated for non-flat overburdens. See the Tutorial at {0} for an explanation.".format(
                "https://github.com/wjwoodley/mute/blob/main/docs/Tutorial.md#calculating-underground-intensities"
            )
        )

    if u_fluxes is None:

        raise Exception(
            "Underground intensities not calculated. The underground flux matrix was not calculated correctly."
        )

    # Calculate the underground intensities

    u_intensities = np.zeros(
        (len(constants._SLANT_DEPTHS), len(constants.ANGLES_FOR_S_FLUXES))
    )

    if constants.get_verbose() > 1:
        print("Calculating underground intensities.")

    for x in range(len(constants._SLANT_DEPTHS)):

        for j in range(len(constants.ANGLES_FOR_S_FLUXES)):

            u_intensities[x, j] = s.simpson(
                u_fluxes[x, E_th_i:, j], constants.ENERGIES[E_th_i:]
            )

    if constants.get_verbose() > 1:
        print("Finished calculating underground intensities.")

    # Create an interpolator object

    try:

        _interpolator

    except NameError:

        _interpolator = _create_interpolator(u_intensities)

    # Interpolate the intensities to the slant depths and zenith angles in the mountain profile file
    # Stack the output into an array for reshaping below

    interpolation_result = np.hstack(
        [
            np.exp(_interpolator(depth, angle))
            for depth, angle in zip(
                constants._mountain_slant_depths_all, constants._mountain_zenith_all
            )
        ]
    )

    # Calculate the intensities at the zenith and azimuthal angles specified in the mountain profile file

    interp_u_intensities = np.nan_to_num(
        np.reshape(
            interpolation_result,
            (len(constants.mountain.zenith), len(constants.mountain.azimuthal)),
        )
    )

    # Write the results to the file

    if output:

        constants._check_directory(
            os.path.join(constants.get_directory(), "underground"), force=force
        )

        if file_name == "" or not isinstance(file_name, str):

            file_name = os.path.join(
                constants.get_directory(),
                "underground",
                "{0}_Underground_Intensities_dd.txt".format(constants.get_lab()),
            )

        file_out = open(file_name, "w")

        for j in range(len(constants.mountain.zenith)):

            for az in range(len(constants.mountain.azimuthal)):

                file_out.write(
                    "{0:1.5f} {1:1.5f} {2:1.14e}\n".format(
                        constants.mountain.zenith[j],
                        constants.mountain.azimuthal[az],
                        interp_u_intensities[j, az],
                    )
                )

        file_out.close()

        if constants.get_verbose() > 1:
            print(f"Underground intensities written to {file_name}.")

    return interp_u_intensities