<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _locate_point(nodes, degree, x_val, y_val):
 r"""Locate a point on a surface. .. note:: There is also a Fortran implementation of this function, which will be used if it can be built. Does so by recursively subdividing the surface and rejecting sub-surfaces with bounding boxes that don't contain the point. After the sub-surfaces are sufficiently small, uses Newton's method to narrow in on the pre-image of the point. Args: nodes (numpy.ndarray):
 Control points for B |eacute| zier surface (assumed to be two-dimensional). degree (int):
 The degree of the surface. x_val (float):
 The :math:`x`-coordinate of a point on the surface. y_val (float):
 The :math:`y`-coordinate of a point on the surface. Returns: Optional[Tuple[float, float]]: The :math:`s` and :math:`t` values corresponding to ``x_val`` and ``y_val`` or :data:`None` if the point is not on the ``surface``. """

    # We track the centroid rather than base_x/base_y/width (by storing triple
    # the centroid -- to avoid division by three until needed). We also need
    # to track the width (or rather, just the sign of the width).
    candidates = [(1.0, 1.0, 1.0, nodes)]
    for _ in six.moves.xrange(MAX_LOCATE_SUBDIVISIONS + 1):
        next_candidates = []
        for candidate in candidates:
            update_locate_candidates(
                candidate, next_candidates, x_val, y_val, degree
            )
        candidates = next_candidates
    if not candidates:
        return None

    # We take the average of all centroids from the candidates
    # that may contain the point.
    s_approx, t_approx = mean_centroid(candidates)
    s, t = newton_refine(nodes, degree, x_val, y_val, s_approx, t_approx)
    actual = _surface_helpers.evaluate_barycentric(
        nodes, degree, 1.0 - s - t, s, t
    )
    expected = np.asfortranarray([x_val, y_val])
    if not _helpers.vector_close(
        actual.ravel(order="F"), expected, eps=LOCATE_EPS
    ):
        s, t = newton_refine(nodes, degree, x_val, y_val, s, t)
    return s, t