def run_imex_sdc(S):
    """
    Routine to run IMEX SDC on a single time step

    Args:
        S: an instance of a step representing the time step

    Returns:
        the error of SDC vs. exact solution
        the residual after the SDC sweeps
        the number of iterations
    """
    # make shortcuts for the level and the problem
    L = S.levels[0]
    P = L.prob

    # set initial time in the status of the level
    L.status.time = 0.1
    # compute initial value (using the exact function here)
    L.u[0] = P.u_exact(L.time)

    # access the sweeper's predict routine to get things started
    # if we don't do this, the values at the nodes are not initialized
    L.sweep.predict()
    # compute the residual (we may be done already!)
    L.sweep.compute_residual()

    # reset iteration counter
    S.status.iter = 0
    # run the SDC iteration until either the maximum number of iterations is reached or the residual is small enough
    f = open('step_2_B_out.txt', 'w')
    while S.status.iter < S.params.maxiter and L.status.residual > L.params.restol:
        # this is where the nodes are actually updated according to the SDC formulas
        L.sweep.update_nodes()
        # compute/update the residual
        L.sweep.compute_residual()
        # increment the iteration counter
        S.status.iter += 1
        out = 'Time %4.2f of %s -- Iteration: %2i -- Residual: %12.8e' \
              % (L.time, L.level_index, S.status.iter, L.status.residual)
        f.write(out + '\n')
        print(out)
    f.close()

    # compute the interval's endpoint: this (and only this) will set uend, depending on the collocation nodes
    L.sweep.compute_end_point()
    # update the simulation time
    L.status.time += L.dt

    # compute exact solution and compare
    uex = P.u_exact(L.status.time)
    err = abs(uex - L.uend)

    return err, L.status.residual, S.status.iter