# Path: rbf/pde/fd.py
# def weight_matrix(x, p, n, diffs,
#                   coeffs=None,
#                   phi='phs3',
#                   order=None,
#                   eps=1.0,
#                   chunk_size=1000):
#     '''
#     Returns a weight matrix which maps a function's values at `p` to an
#     approximation of that function's derivative at `x`. This is a convenience
#     function which first creates stencils and then computes the RBF-FD weights
#     for each stencil.
# 
#     Parameters
#     ----------
#     x : (N, D) float array
#         Target points where the derivative is being approximated
# 
#     p : (M, D) array
#         Source points. The derivatives will be approximated with a weighted sum
#         of values at these point.
# 
#     n : int
#         The stencil size. Each target point will have a stencil made of the `n`
#         nearest neighbors from `p`
# 
#     diffs : (D,) int array or (K, D) int array
#         Derivative orders for each spatial dimension. For example `[2, 0]`
#         indicates that the weights should approximate the second derivative
#         with respect to the first spatial dimension in two-dimensional space.
#         `diffs` can also be a (K, D) array, where each (D,) sub-array is a term
#         in a differential operator. For example the two-dimensional Laplacian
#         can be represented as `[[2, 0], [0, 2]]`.
# 
#     coeffs : (K,) or (K, N) float array, optional
#         Coefficients for each term in the differential operator specified with
#         `diffs`. The coefficients can vary between target points. Defaults to
#         an array of ones.
# 
#     phi : rbf.basis.RBF instance or str, optional
#         Type of RBF. Select from those available in `rbf.basis` or create your
#         own.
# 
#     order : int, optional
#         Order of the added polynomial. This defaults to the highest derivative
#         order. For example, if `diffs` is `[[2, 0], [0, 1]]`, then this is set
#         to 2.
# 
#     eps : float, optional
#         Shape parameter for each RBF
# 
#     chunk_size : int, optional
#         Break the target points into chunks with this size to reduce the memory
#         requirements
# 
#     Returns
#     -------
#     (N, M) coo sparse matrix
# 
#     Examples
#     --------
#     Create a second order differentiation matrix in one-dimensional space
# 
#     >>> x = np.arange(4.0)[:, None]
#     >>> W = weight_matrix(x, x, 3, (2,))
#     >>> W.toarray()
#     array([[ 1., -2.,  1., 0.],
#            [ 1., -2.,  1., 0.],
#            [ 0.,  1., -2., 1.],
#            [ 0.,  1., -2., 1.]])
# 
#     '''
#     x = np.asarray(x, dtype=float)
#     assert_shape(x, (None, None), 'x')
#     nx, ndim = x.shape
# 
#     p = np.asarray(p, dtype=float)
#     assert_shape(p, (None, ndim), 'p')
# 
#     diffs = np.asarray(diffs, dtype=int)
#     diffs = np.atleast_2d(diffs)
#     assert_shape(diffs, (None, ndim), 'diffs')
# 
#     if coeffs is None:
#         coeffs = np.ones(len(diffs), dtype=float)
#     else:
#         coeffs = np.asarray(coeffs, dtype=float)
#         assert_shape(coeffs, (len(diffs), ...), 'coeffs')
# 
#     # broadcast each element in `coeffs` to the length of `x`
#     coeffs = np.array([np.broadcast_to(c, (nx,)) for c in coeffs])
# 
#     _, stencils = KDTree(p).query(x, n)
#     if chunk_size is None:
#         data = weights(
#             x, p[stencils], diffs,
#             coeffs=coeffs,
#             phi=phi,
#             order=order,
#             eps=eps)
#     else:
#         data = np.empty((nx, n), dtype=float)
#         for start in range(0, nx, chunk_size):
#             stop = start + chunk_size
#             data[start:stop] = weights(
#                 x[start:stop], p[stencils[start:stop]], diffs,
#                 coeffs=coeffs[:, start:stop],
#                 phi=phi,
#                 order=order,
#                 eps=eps)
# 
#     data = data.ravel()
#     rows = np.repeat(range(nx), n)
#     cols = stencils.ravel()
#     out = sp.coo_matrix((data, (rows, cols)), (nx, len(p)))
#     return out


from rbf.pde.fd import weight_matrix
            'zx':D_zx, 'zy':D_zy, 'zz':D_zz}


def elastic3d_displacement(x, p, n, **kwargs):
    '''
    Returns weight matrices that map displacements at `p` to the displacements
    at `x`.

    Parameters
    ----------
    x: (N, 3) array
        target points.

    p: (M, 3) array
        observation points.

    n : int
        stencil size

    **kwargs:
        additional arguments passed to `weight_matrix`

    Returns
    -------
    dict
        keys are the components and the values are the corresponding weight
        matrices.

    '''
    D_xx = weight_matrix(x, p, n, (0, 0, 0), **kwargs)

# Path: rbf/pde/fd.py
# def weight_matrix(x, p, n, diffs,
#                   coeffs=None,
#                   phi='phs3',
#                   order=None,
#                   eps=1.0,
#                   chunk_size=1000):
#     '''
#     Returns a weight matrix which maps a function's values at `p` to an
#     approximation of that function's derivative at `x`. This is a convenience
#     function which first creates stencils and then computes the RBF-FD weights
#     for each stencil.
# 
#     Parameters
#     ----------
#     x : (N, D) float array
#         Target points where the derivative is being approximated
# 
#     p : (M, D) array
#         Source points. The derivatives will be approximated with a weighted sum
#         of values at these point.
# 
#     n : int
#         The stencil size. Each target point will have a stencil made of the `n`
#         nearest neighbors from `p`
# 
#     diffs : (D,) int array or (K, D) int array
#         Derivative orders for each spatial dimension. For example `[2, 0]`
#         indicates that the weights should approximate the second derivative
#         with respect to the first spatial dimension in two-dimensional space.
#         `diffs` can also be a (K, D) array, where each (D,) sub-array is a term
#         in a differential operator. For example the two-dimensional Laplacian
#         can be represented as `[[2, 0], [0, 2]]`.
# 
#     coeffs : (K,) or (K, N) float array, optional
#         Coefficients for each term in the differential operator specified with
#         `diffs`. The coefficients can vary between target points. Defaults to
#         an array of ones.
# 
#     phi : rbf.basis.RBF instance or str, optional
#         Type of RBF. Select from those available in `rbf.basis` or create your
#         own.
# 
#     order : int, optional
#         Order of the added polynomial. This defaults to the highest derivative
#         order. For example, if `diffs` is `[[2, 0], [0, 1]]`, then this is set
#         to 2.
# 
#     eps : float, optional
#         Shape parameter for each RBF
# 
#     chunk_size : int, optional
#         Break the target points into chunks with this size to reduce the memory
#         requirements
# 
#     Returns
#     -------
#     (N, M) coo sparse matrix
# 
#     Examples
#     --------
#     Create a second order differentiation matrix in one-dimensional space
# 
#     >>> x = np.arange(4.0)[:, None]
#     >>> W = weight_matrix(x, x, 3, (2,))
#     >>> W.toarray()
#     array([[ 1., -2.,  1., 0.],
#            [ 1., -2.,  1., 0.],
#            [ 0.,  1., -2., 1.],
#            [ 0.,  1., -2., 1.]])
# 
#     '''
#     x = np.asarray(x, dtype=float)
#     assert_shape(x, (None, None), 'x')
#     nx, ndim = x.shape
# 
#     p = np.asarray(p, dtype=float)
#     assert_shape(p, (None, ndim), 'p')
# 
#     diffs = np.asarray(diffs, dtype=int)
#     diffs = np.atleast_2d(diffs)
#     assert_shape(diffs, (None, ndim), 'diffs')
# 
#     if coeffs is None:
#         coeffs = np.ones(len(diffs), dtype=float)
#     else:
#         coeffs = np.asarray(coeffs, dtype=float)
#         assert_shape(coeffs, (len(diffs), ...), 'coeffs')
# 
#     # broadcast each element in `coeffs` to the length of `x`
#     coeffs = np.array([np.broadcast_to(c, (nx,)) for c in coeffs])
# 
#     _, stencils = KDTree(p).query(x, n)
#     if chunk_size is None:
#         data = weights(
#             x, p[stencils], diffs,
#             coeffs=coeffs,
#             phi=phi,
#             order=order,
#             eps=eps)
#     else:
#         data = np.empty((nx, n), dtype=float)
#         for start in range(0, nx, chunk_size):
#             stop = start + chunk_size
#             data[start:stop] = weights(
#                 x[start:stop], p[stencils[start:stop]], diffs,
#                 coeffs=coeffs[:, start:stop],
#                 phi=phi,
#                 order=order,
#                 eps=eps)
# 
#     data = data.ravel()
#     rows = np.repeat(range(nx), n)
#     cols = stencils.ravel()
#     out = sp.coo_matrix((data, (rows, cols)), (nx, len(p)))
#     return out


# Path: rbf/pde/elastic.py
from rbf.pde.fd import weight_matrix

            'zx':D_zx, 'zy':D_zy, 'zz':D_zz}


def elastic3d_displacement(x, p, n, **kwargs):
    '''
    Returns weight matrices that map displacements at `p` to the displacements
    at `x`.

    Parameters
    ----------
    x: (N, 3) array
        target points.

    p: (M, 3) array
        observation points.

    n : int
        stencil size

    **kwargs:
        additional arguments passed to `weight_matrix`

    Returns
    -------
    dict
        keys are the components and the values are the corresponding weight
        matrices.

    '''
    D_xx = weight_matrix(x, p, n, (0, 0, 0), **kwargs)

    D_yy = weight_matrix(x, p, n, (0, 0, 0), **kwargs)