a
    Sic                     @   s  d Z ddlZddlmZ ddlmZ ddlmZ ddl	m
Z
 dZG dd	 d	ZG d
d deZG dd deZG dd dZG dd dZG dd deZG dd deZG dd deZG dd dZd,ddZdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ ZdS )-z(
Interpolation inside triangular grids.
    N)_api)Triangulation)	TriFinder)TriAnalyzer)TriInterpolatorLinearTriInterpolatorCubicTriInterpolatorc                   @   s4   e Zd ZdZdddZdZdZddd	Zd
d ZdS )r   am  
    Abstract base class for classes used to interpolate on a triangular grid.

    Derived classes implement the following methods:

    - ``__call__(x, y)``,
      where x, y are array-like point coordinates of the same shape, and
      that returns a masked array of the same shape containing the
      interpolated z-values.

    - ``gradient(x, y)``,
      where x, y are array-like point coordinates of the same
      shape, and that returns a list of 2 masked arrays of the same shape
      containing the 2 derivatives of the interpolator (derivatives of
      interpolated z values with respect to x and y).
    Nc                 C   sr   t jt|d || _t|| _| jj| jjjkr:t	dt jt
d f|d |pX| j | _d| _d| _d | _d S )N)triangulationz=z array must have same length as triangulation x and y arrays)	trifinder      ?)r   check_isinstancer   _triangulationnpasarray_zshapex
ValueErrorr   get_trifinder
_trifinder_unit_x_unit_y
_tri_renumselfr	   zr
    r   Y/var/www/html/django/DPS/env/lib/python3.9/site-packages/matplotlib/tri/triinterpolate.py__init__!   s    zTriInterpolator.__init__a  
        Returns a masked array containing interpolated values at the specified
        (x, y) points.

        Parameters
        ----------
        x, y : array-like
            x and y coordinates of the same shape and any number of
            dimensions.

        Returns
        -------
        np.ma.array
            Masked array of the same shape as *x* and *y*; values corresponding
            to (*x*, *y*) points outside of the triangulation are masked out.

        a  
        Returns a list of 2 masked arrays containing interpolated derivatives
        at the specified (x, y) points.

        Parameters
        ----------
        x, y : array-like
            x and y coordinates of the same shape and any number of
            dimensions.

        Returns
        -------
        dzdx, dzdy : np.ma.array
            2 masked arrays of the same shape as *x* and *y*; values
            corresponding to (x, y) points outside of the triangulation
            are masked out.
            The first returned array contains the values of
            :math:`\frac{\partial z}{\partial x}` and the second those of
            :math:`\frac{\partial z}{\partial y}`.

        r   c                 C   s  t j|t jd}t j|t jd}|j}|j|jkrFtd|j|jt |}t |}|| j }|| j }t 	|}|du r| 
||}n&|j|krtd|j|t |}|dk}	| jdu r||	 }
n| j||	  }
||	 }||	 }g }|D ]}zdddd	| }W n0 ty> } ztd
|W Y d}~n
d}~0 0 dd| j d| j g| }t j|t jd}t j||	 < | ||
||| ||	< |t jj||ddg7 }q|S )a	  
        Versatile (private) method defined for all TriInterpolators.

        :meth:`_interpolate_multikeys` is a wrapper around method
        :meth:`_interpolate_single_key` (to be defined in the child
        subclasses).
        :meth:`_interpolate_single_key actually performs the interpolation,
        but only for 1-dimensional inputs and at valid locations (inside
        unmasked triangles of the triangulation).

        The purpose of :meth:`_interpolate_multikeys` is to implement the
        following common tasks needed in all subclasses implementations:

        - calculation of containing triangles
        - dealing with more than one interpolation request at the same
          location (e.g., if the 2 derivatives are requested, it is
          unnecessary to compute the containing triangles twice)
        - scaling according to self._unit_x, self._unit_y
        - dealing with points outside of the grid (with fill value np.nan)
        - dealing with multi-dimensional *x*, *y* arrays: flattening for
          :meth:`_interpolate_params` call and final reshaping.

        (Note that np.vectorize could do most of those things very well for
        you, but it does it by function evaluations over successive tuples of
        the input arrays. Therefore, this tends to be more time consuming than
        using optimized numpy functions - e.g., np.dot - which can be used
        easily on the flattened inputs, in the child-subclass methods
        :meth:`_interpolate_single_key`.)

        It is guaranteed that the calls to :meth:`_interpolate_single_key`
        will be done with flattened (1-d) array-like input parameters *x*, *y*
        and with flattened, valid `tri_index` arrays (no -1 index allowed).

        Parameters
        ----------
        x, y : array-like
            x and y coordinates where interpolated values are requested.
        tri_index : array-like of int, optional
            Array of the containing triangle indices, same shape as
            *x* and *y*. Defaults to None. If None, these indices
            will be computed by a TriFinder instance.
            (Note: For point outside the grid, tri_index[ipt] shall be -1).
        return_keys : tuple of keys from {'z', 'dzdx', 'dzdy'}
            Defines the interpolation arrays to return, and in which order.

        Returns
        -------
        list of arrays
            Each array-like contains the expected interpolated values in the
            order defined by *return_keys* parameter.
        dtypez2x and y shall have same shapes. Given: {0} and {1}NzTtri_index array is provided and shall have same shape as x and y. Given: {0} and {1}r         r   dzdxdzdyz<return_keys items shall take values in {'z', 'dzdx', 'dzdy'}r   F)copy)r   r   float64r   r   formatravelr   r   sizer   r   KeyErroremptynan_interpolate_single_keymamasked_invalidreshape)r   r   y	tri_indexreturn_keysZsh_retZx_scaledZy_scaledZsize_retZmask_inZvalid_tri_indexZvalid_xZvalid_yret
return_keyreturn_indexerrscaleZret_locr   r   r   _interpolate_multikeysf   sZ    7








z&TriInterpolator._interpolate_multikeysc                 C   s   t ddS )a+  
        Interpolate at points belonging to the triangulation
        (inside an unmasked triangles).

        Parameters
        ----------
        return_key : {'z', 'dzdx', 'dzdy'}
            The requested values (z or its derivatives).
        tri_index : 1D int array
            Valid triangle index (cannot be -1).
        x, y : 1D arrays, same shape as `tri_index`
            Valid locations where interpolation is requested.

        Returns
        -------
        1-d array
            Returned array of the same size as *tri_index*
        zCTriInterpolator subclassesshould implement _interpolate_single_key!NNotImplementedErrorr   r8   r5   r   r4   r   r   r   r0      s    z'TriInterpolator._interpolate_single_key)N)Nr   )	__name__
__module____qualname____doc__r   _docstring__call___docstringgradientr<   r0   r   r   r   r   r      s   
  
kr   c                       sJ   e Zd ZdZd fdd	Zdd Zeje_dd Zej	e_d	d
 Z
  ZS )r   a  
    Linear interpolator on a triangular grid.

    Each triangle is represented by a plane so that an interpolated value at
    point (x, y) lies on the plane of the triangle containing (x, y).
    Interpolated values are therefore continuous across the triangulation, but
    their first derivatives are discontinuous at edges between triangles.

    Parameters
    ----------
    triangulation : `~matplotlib.tri.Triangulation`
        The triangulation to interpolate over.
    z : (npoints,) array-like
        Array of values, defined at grid points, to interpolate between.
    trifinder : `~matplotlib.tri.TriFinder`, optional
        If this is not specified, the Triangulation's default TriFinder will
        be used by calling `.Triangulation.get_trifinder`.

    Methods
    -------
    `__call__` (x, y) : Returns interpolated values at (x, y) points.
    `gradient` (x, y) : Returns interpolated derivatives at (x, y) points.

    Nc                    s$   t  ||| | j| j| _d S N)superr   r   calculate_plane_coefficientsr   _plane_coefficientsr   	__class__r   r   r     s    zLinearTriInterpolator.__init__c                 C   s   | j ||d ddd S Nr   r5   r6   r   r<   r   r   r4   r   r   r   __call__  s
    
zLinearTriInterpolator.__call__c                 C   s   | j ||d ddS N)r&   r'   rM   rN   rO   r   r   r   gradient  s    
zLinearTriInterpolator.gradientc                 C   st   t jg d|d |dkrL| j|df | | j|df |  | j|df  S |dkrb| j|df S | j|df S d S )Nr%   r8   r   r   r#   r$   r&   )r   check_in_listrI   r?   r   r   r   r0     s    z-LinearTriInterpolator._interpolate_single_key)N)r@   rA   rB   rC   r   rP   r   rD   rR   rE   r0   __classcell__r   r   rJ   r   r      s   r   c                       sx   e Zd ZdZd fdd	Zdd Zeje_dd	 Zej	e_d
d Z
dddZedd Zedd Zedd Z  ZS )r   ag  
    Cubic interpolator on a triangular grid.

    In one-dimension - on a segment - a cubic interpolating function is
    defined by the values of the function and its derivative at both ends.
    This is almost the same in 2D inside a triangle, except that the values
    of the function and its 2 derivatives have to be defined at each triangle
    node.

    The CubicTriInterpolator takes the value of the function at each node -
    provided by the user - and internally computes the value of the
    derivatives, resulting in a smooth interpolation.
    (As a special feature, the user can also impose the value of the
    derivatives at each node, but this is not supposed to be the common
    usage.)

    Parameters
    ----------
    triangulation : `~matplotlib.tri.Triangulation`
        The triangulation to interpolate over.
    z : (npoints,) array-like
        Array of values, defined at grid points, to interpolate between.
    kind : {'min_E', 'geom', 'user'}, optional
        Choice of the smoothing algorithm, in order to compute
        the interpolant derivatives (defaults to 'min_E'):

        - if 'min_E': (default) The derivatives at each node is computed
          to minimize a bending energy.
        - if 'geom': The derivatives at each node is computed as a
          weighted average of relevant triangle normals. To be used for
          speed optimization (large grids).
        - if 'user': The user provides the argument *dz*, no computation
          is hence needed.

    trifinder : `~matplotlib.tri.TriFinder`, optional
        If not specified, the Triangulation's default TriFinder will
        be used by calling `.Triangulation.get_trifinder`.
    dz : tuple of array-likes (dzdx, dzdy), optional
        Used only if  *kind* ='user'. In this case *dz* must be provided as
        (dzdx, dzdy) where dzdx, dzdy are arrays of the same shape as *z* and
        are the interpolant first derivatives at the *triangulation* points.

    Methods
    -------
    `__call__` (x, y) : Returns interpolated values at (x, y) points.
    `gradient` (x, y) : Returns interpolated derivatives at (x, y) points.

    Notes
    -----
    This note is a bit technical and details how the cubic interpolation is
    computed.

    The interpolation is based on a Clough-Tocher subdivision scheme of
    the *triangulation* mesh (to make it clearer, each triangle of the
    grid will be divided in 3 child-triangles, and on each child triangle
    the interpolated function is a cubic polynomial of the 2 coordinates).
    This technique originates from FEM (Finite Element Method) analysis;
    the element used is a reduced Hsieh-Clough-Tocher (HCT)
    element. Its shape functions are described in [1]_.
    The assembled function is guaranteed to be C1-smooth, i.e. it is
    continuous and its first derivatives are also continuous (this
    is easy to show inside the triangles but is also true when crossing the
    edges).

    In the default case (*kind* ='min_E'), the interpolant minimizes a
    curvature energy on the functional space generated by the HCT element
    shape functions - with imposed values but arbitrary derivatives at each
    node. The minimized functional is the integral of the so-called total
    curvature (implementation based on an algorithm from [2]_ - PCG sparse
    solver):

        .. math::

            E(z) = \frac{1}{2} \int_{\Omega} \left(
                \left( \frac{\partial^2{z}}{\partial{x}^2} \right)^2 +
                \left( \frac{\partial^2{z}}{\partial{y}^2} \right)^2 +
                2\left( \frac{\partial^2{z}}{\partial{y}\partial{x}} \right)^2
            \right) dx\,dy

    If the case *kind* ='geom' is chosen by the user, a simple geometric
    approximation is used (weighted average of the triangle normal
    vectors), which could improve speed on very large grids.

    References
    ----------
    .. [1] Michel Bernadou, Kamal Hassan, "Basis functions for general
        Hsieh-Clough-Tocher triangles, complete or reduced.",
        International Journal for Numerical Methods in Engineering,
        17(5):784 - 789. 2.01.
    .. [2] C.T. Kelley, "Iterative Methods for Optimization".

    min_ENc                    s   t  ||| | j  t| j}| \}}}	}
}|| _|
| _|dk}| j| | j|| < t	
|| _t	
|	| _t	|| j |	| j g| _| j| j | _| | j| _tjg d|d | j||d| _t | _d S )Nr"   )usergeomrV   )kinddz)rG   r   r   get_cpp_triangulationr   Z_get_compressed_triangulation
_trianglesr   r   r   ptpr   r   column_stack_pts	_tris_pts_compute_tri_eccentricities_eccsr   rT   _compute_dof_dof_ReducedHCT_Element_ReferenceElement)r   r	   r   rY   r
   r[   Ztri_analyzerZcompressed_trianglesZcompressed_xZcompressed_yZ	tri_renumZ
node_renumZ
valid_noderJ   r   r   r   {  s(    



zCubicTriInterpolator.__init__c                 C   s   | j ||d ddd S rL   rN   rO   r   r   r   rP     s
    
zCubicTriInterpolator.__call__c                 C   s   | j ||d ddS rQ   rN   rO   r   r   r   rR     s    
zCubicTriInterpolator.gradientc                 C   s   t jg d|d | j| }| |||}| j| }tj| j| dd}|dkr`| j	|||S | 
|}	| j||	||}
|dkr|
d d ddf S |
d d ddf S d S )Nr%   rS   r#   axisr   r&   r   )r   rT   ra   _get_alpha_vecrc   r   expand_dimsre   rg   get_function_values_get_jacobianget_function_derivatives)r   r8   r5   r   r4   tris_ptsalphaeccdofJr&   r   r   r   r0     s     


z,CubicTriInterpolator._interpolate_single_keyc                 C   sH   |dkr&|du rt dt| |d}n|dkr8t| }nt| }| S )aR  
        Compute and return nodal dofs according to kind.

        Parameters
        ----------
        kind : {'min_E', 'geom', 'user'}
            Choice of the _DOF_estimator subclass to estimate the gradient.
        dz : tuple of array-likes (dzdx, dzdy), optional
            Used only if *kind*=user; in this case passed to the
            :class:`_DOF_estimator_user`.

        Returns
        -------
        array-like, shape (npts, 2)
            Estimation of the gradient at triangulation nodes (stored as
            degree of freedoms of reduced-HCT triangle elements).
        rW   NzQFor a CubicTriInterpolator with *kind*='user', a valid *dz* argument is expected.rZ   rX   )r   _DOF_estimator_user_DOF_estimator_geom_DOF_estimator_min_Ecompute_dof_from_df)r   rY   r[   ZTEr   r   r   rd     s    
z!CubicTriInterpolator._compute_dofc                 C   s(  |j d }|dddddf |dddddf  }|dddddf |dddddf  }tj||gdd}t|}tj| |gdd|dddddf  }|| }	t|	}
|tt|| }|
| }td|ddddf  |ddddf  g|ddddf g|ddddf gg}|S )a2  
        Fast (vectorized) function to compute barycentric coordinates alpha.

        Parameters
        ----------
        x, y : array-like of dim 1 (shape (nx,))
            Coordinates of the points whose points barycentric coordinates are
            requested.
        tris_pts : array like of dim 3 (shape: (nx, 3, 2))
            Coordinates of the containing triangles apexes.

        Returns
        -------
        array of dim 2 (shape (nx, 3))
            Barycentric coordinates of the points inside the containing
            triangles.
        r$   Nr#   r   r"   rh   )ndimr   stack_transpose_vectorized_pseudo_inv22sym_vectorizedrk   _to_matrix_vectorized)r   r4   ro   rx   abZabTabZOMmetricZ
metric_invZCovarksirp   r   r   r   rj     s    
,,(Lz#CubicTriInterpolator._get_alpha_vecc                 C   s   t | dddddf | dddddf  }t | dddddf | dddddf  }t|dddf |dddf g|dddf |dddf gg}|S )a  
        Fast (vectorized) function to compute triangle jacobian matrix.

        Parameters
        ----------
        tris_pts : array like of dim 3 (shape: (nx, 3, 2))
            Coordinates of the containing triangles apexes.

        Returns
        -------
        array of dim 3 (shape (nx, 2, 2))
            Barycentric coordinates of the points inside the containing
            triangles.
            J[itri, :, :] is the jacobian matrix at apex 0 of the triangle
            itri, so that the following (matrix) relationship holds:
               [dz/dksi] = [J] x [dz/dx]
            with x: global coordinates
                 ksi: element parametric coordinates in triangle first apex
                 local basis.
        Nr#   r   r$   )r   arrayr|   )ro   r}   r~   rs   r   r   r   rm     s    22 z"CubicTriInterpolator._get_jacobianc                 C   s  t j| dddddf | dddddf  dd}t j| dddddf | dddddf  dd}t j| dddddf | dddddf  dd}t|| ddddf }t|| ddddf }t|| ddddf }t|| | g|| | g|| | ggS )ax  
        Compute triangle eccentricities.

        Parameters
        ----------
        tris_pts : array like of dim 3 (shape: (nx, 3, 2))
            Coordinates of the triangles apexes.

        Returns
        -------
        array like of dim 2 (shape: (nx, 3))
            The so-called eccentricity parameters [1] needed for HCT triangular
            element.
        Nr$   r#   rh   r   )r   rk   rz   r|   )ro   r}   r~   cZdot_aZdot_bZdot_cr   r   r   rb   !  s    666z0CubicTriInterpolator._compute_tri_eccentricities)rV   NN)N)r@   rA   rB   rC   r   rP   r   rD   rR   rE   r0   rd   staticmethodrj   rm   rb   rU   r   r   rJ   r   r     s    \  )

&
r   c                   @   s`  e Zd ZdZeg dg dg dg dg dg dg dg d	g d
g	Zeg dg dg dg dg dg dg dg dg dg	Zeg dg dg dg dg dg dg dg dg dg	Zeg dg dg dg dg dg dg dg dg dg	Z	eddgddgddgddgddgddggZ
eg dg dg dg dg dg dg dg dg d g	Zd!Zejg d"g d#g d$g d%g d&g d'g d(g d)g d*g	ejd+Zejd!gejd+d, Zeg dg dg d-gZeddgddggZeddgddggZd.d/ Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd>d9d:Zd;d< Zd=S )?rf   aN  
    Implementation of reduced HCT triangular element with explicit shape
    functions.

    Computes z, dz, d2z and the element stiffness matrix for bending energy:
    E(f) = integral( (d2z/dx2 + d2z/dy2)**2 dA)

    *** Reference for the shape functions: ***
    [1] Basis functions for general Hsieh-Clough-Tocher _triangles, complete or
        reduced.
        Michel Bernadou, Kamal Hassan
        International Journal for Numerical Methods in Engineering.
        17(5):784 - 789.  2.01

    *** Element description: ***
    9 dofs: z and dz given at 3 apex
    C1 (conform)

    )
        r   r         @r   r   r   r   r   r   )
      пr   r         ?      ?r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )
r   r   r         r         @r   r   r   r   )
r   r   r   r         ?r   r   r   r   r   )
r   r   r         r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )
      r   r         ?r   r   r   r   r         )
r   r   r         ?r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )
r   r   r         r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   r   r   r   )r   r   r   )r   r   r   )r   r   r   )r   r   r   )r          r   )r   r   r   	   )qq?qq?qq?)r   r   r   )98?r   r   )r   r   r   )r   r   r   )r   r   r   )r   r   r   )r   r   r   )r   r   r   r    g      "@)r   r          @c                 C   s|  t j|dddddf }t|| dd}t|| dd}|ddddf }|ddddf }|ddddf }	|| }
|| }|	|	 }t|
| g|| g||	 g|
|	 g|
| g|| g||	 g|| g|| g|| |	 gg
}| j| }|t|ddddf | j| 7 }|t|ddddf | j| 7 }|t|ddddf | j| 7 }t|d| dd}|| ddddf S )a  
        Parameters
        ----------
        alpha : is a (N x 3 x 1) array (array of column-matrices) of
        barycentric coordinates,
        ecc : is a (N x 3 x 1) array (array of column-matrices) of triangle
        eccentricities,
        dofs : is a (N x 1 x 9) arrays (arrays of row-matrices) of computed
        degrees of freedom.

        Returns
        -------
        Returns the N-array of interpolated function values.
        r#   rh   Nr   r$      )	r   argmin_roll_vectorizedr|   M_scalar_vectorizedM0M1M2)r   rp   rq   dofssubtrir   Er   r4   r   x_sqy_sqz_sqVprodsr   r   r   rl     s&    0$
"""z'_ReducedHCT_Element.get_function_valuesc                 C   s   t j|dddddf }t|| dd}t|| dd}|ddddf }|ddddf }	|ddddf }
|| }|	|	 }|
|
 }td| d| gd| dgdd| gd	| |
 d	| |
 | gd	| |	 | d	| |	 gd
| |	 | | gd
|	 |
 |g|d
|	 |
 g| d
| |
 | g||
 |	|
  ||	 |	|
  gg
}|t| j|ddd }| j| }|t|ddddf | j| 7 }|t|ddddf | j	| 7 }|t|ddddf | j
| 7 }t|d| dd}|| }t|}|t| }|S )a  
        Parameters
        ----------
        *alpha* is a (N x 3 x 1) array (array of column-matrices of
        barycentric coordinates)
        *J* is a (N x 2 x 2) array of jacobian matrices (jacobian matrix at
        triangle first apex)
        *ecc* is a (N x 3 x 1) array (array of column-matrices of triangle
        eccentricities)
        *dofs* is a (N x 1 x 9) arrays (arrays of row-matrices) of computed
        degrees of freedom.

        Returns
        -------
        Returns the values of interpolated function derivatives [dz/dx, dz/dy]
        in global coordinates at locations alpha, as a column-matrices of
        shape (N x 2 x 1).
        r#   rh   Nr   r$   r   r   r   r   r   
block_sizeri   r   )r   r   r   r|   _extract_submatrices	rotate_dVr   r   r   r   r   _safe_inv22_vectorizedrz   )r   rp   rs   rq   r   r   r   r   r   r4   r   r   r   r   ZdVr   ZdsdksidfdksiJ_invZdfdxr   r   r   rn     sB    



"""z,_ReducedHCT_Element.get_function_derivativesc           	      C   s.   |  ||}|| }| |}|| }t|S )a  
        Parameters
        ----------
        *alpha* is a (N x 3 x 1) array (array of column-matrices) of
        barycentric coordinates
        *J* is a (N x 2 x 2) array of jacobian matrices (jacobian matrix at
        triangle first apex)
        *ecc* is a (N x 3 x 1) array (array of column-matrices) of triangle
        eccentricities
        *dofs* is a (N x 1 x 9) arrays (arrays of row-matrices) of computed
        degrees of freedom.

        Returns
        -------
        Returns the values of interpolated function 2nd-derivatives
        [d2z/dx2, d2z/dy2, d2z/dxdy] in global coordinates at locations alpha,
        as a column-matrices of shape (N x 3 x 1).
        )get_d2Sidksij2get_Hrot_from_Jrz   )	r   rp   rs   rq   r   d2sdksi2Zd2fdksi2H_rotZd2fdx2r   r   r   get_function_hessians  s
    
z)_ReducedHCT_Element.get_function_hessiansc                 C   s  t j|dddddf }t|| dd}t|| dd}|ddddf }|ddddf }|ddddf }td| d| d| gd| ddgdd| dgd| d| d	|  d| d|  gd| d	|  d| d| d|  gd| d	|  dd
| gd| dd| gdd| d| gdd| d	|  d
| gd
| d
| || | gg
}	|	t| j|ddd }	| j|	 }
|
t|ddddf | j|	 7 }
|
t|ddddf | j	|	 7 }
|
t|ddddf | j
|	 7 }
t|
d| dd}|S )a  
        Parameters
        ----------
        *alpha* is a (N x 3 x 1) array (array of column-matrices) of
        barycentric coordinates
        *ecc* is a (N x 3 x 1) array (array of column-matrices) of triangle
        eccentricities

        Returns
        -------
        Returns the arrays d2sdksi2 (N x 3 x 1) Hessian of shape functions
        expressed in covariant coordinates in first apex basis.
        r#   rh   Nr   r$   g      @r   r   g      @r   r   r   )r   r   r   r|   r   
rotate_d2Vr   r   r   r   r   )r   rp   rq   r   r   r   r   r4   r   Zd2Vr   r   r   r   r   r     s6    $$

"""z"_ReducedHCT_Element.get_d2Sidksij2c                 C   sz  t |d}| j| }| j| }t j|ddgt jd}d|ddddf< d|ddddf< d|ddddf< ||ddddddf< ||ddddddf< ||ddd	dd	df< | j|d
d\}}t j|ddgt jd}	| j}
| j}t	| j
D ]f}t ||ddf ||d}t |d}|
| }| ||}|| }|	||| j t|  7 }	qt||	 | }	t||	S )a  
        Parameters
        ----------
        *J* is a (N x 2 x 2) array of jacobian matrices (jacobian matrix at
        triangle first apex)
        *ecc* is a (N x 3 x 1) array (array of column-matrices) of triangle
        eccentricities

        Returns
        -------
        Returns the element K matrices for bending energy expressed in
        GLOBAL nodal coordinates.
        K_ij = integral [ (d2zi/dx2 + d2zi/dy2) * (d2zj/dx2 + d2zj/dy2) dA]
        tri_J is needed to rotate dofs from local basis to global basis
        r   r   r    r#   Nr            T)return_arear$   )r   r,   J0_to_J1J0_to_J2zerosr)   r   gauss_w	gauss_ptsrangen_gausstiler3   rk   r   r   rz   r   )r   rs   rq   nJ1J2ZDOF_rotr   areaKweightsptsZigaussrp   weightZ	d2Skdksi2Zd2Skdx2r   r   r   get_bending_matrices>  s.    

 z(_ReducedHCT_Element.get_bending_matricesFc           
      C   s  t |}|ddddf }|ddddf }|ddddf }|ddddf }t|| || || g|| || || gd| | d| | || ||  gg}|s|S d|ddddf |ddddf  |ddddf |ddddf    }	||	fS dS )as  
        Parameters
        ----------
        *J* is a (N x 2 x 2) array of jacobian matrices (jacobian matrix at
        triangle first apex)

        Returns
        -------
        Returns H_rot used to rotate Hessian from local basis of first apex,
        to global coordinates.
        if *return_area* is True, returns also the triangle area (0.5*det(J))
        Nr   r#   r$   r   )r   r|   )
r   rs   r   r   ZJi00ZJi11ZJi10ZJi01r   r   r   r   r   r   q  s    $Lz#_ReducedHCT_Element.get_Hrot_from_Jc                 C   s  t |d}t j|t jd}t j|dt jd}g d}g d}	t||dddf d |dddf d d ||dddf d |dddf d d ||dddf d |dddf d d g	g}
t j|d	dgt jd}t||
 }||
 }| ||}t 	|t 
||| }t 	|t 
||| }t 	|t 
||| }|t 
|||	 }t j|dd
}|| dddddf  }|
t 
|dg| dddddf }t jt 	|t 	|d}||||fS )aF  
        Build K and F for the following elliptic formulation:
        minimization of curvature energy with value of function at node
        imposed and derivatives 'free'.

        Build the global Kff matrix in cco format.
        Build the full Ff vec Ff = - Kfc x Uc.

        Parameters
        ----------
        *J* is a (N x 2 x 2) array of jacobian matrices (jacobian matrix at
        triangle first apex)
        *ecc* is a (N x 3 x 1) array (array of column-matrices) of triangle
        eccentricities
        *triangles* is a (N x 3) array of nodes indexes.
        *Uc* is (N x 3) array of imposed displacements at nodes

        Returns
        -------
        (Kff_rows, Kff_cols, Kff_vals) Kff matrix in coo format - Duplicate
        (row, col) entries must be summed.
        Ff: force vector - dim npts * 3
        r   r    r"   )r#   r$   r      r      )r   r   r   Nr$   r#   r   rh   r   )r   r,   arangeint32fullr|   onesrz   r   r+   ix_rk   bincount)r   rs   rq   	trianglesUcZntriZ	vec_rangeZ	c_indicesZf_dofZc_dofZf_dof_indicesZexpand_indicesZf_row_indicesZf_col_indicesZK_elemKff_valsKff_rowsKff_colsZKfc_elemZUc_elemZFf_elemZ
Ff_indicesFfr   r   r   get_Kff_and_Ff  s.    ***&z"_ReducedHCT_Element.get_Kff_and_FfN)F)r@   rA   rB   rC   r   r   r   r   r   r   r   r   r   r)   r   r   r   r   r   r   rl   rn   r   r   r   r   r   r   r   r   r   rf   B  s   



	"8)3
rf   c                   @   s4   e Zd ZdZdd Zdd Zdd Zedd	 Zd
S )_DOF_estimatoral  
    Abstract base class for classes used to estimate a function's first
    derivatives, and deduce the dofs for a CubicTriInterpolator using a
    reduced HCT element formulation.

    Derived classes implement ``compute_df(self, **kwargs)``, returning
    ``np.vstack([dfx, dfy]).T`` where ``dfx, dfy`` are the estimation of the 2
    gradient coordinates.
    c                 K   s^   t jt|d |j| _|j| _|j| _|j| _|j|j	 | _| _	| j
f i || _|   d S )N)interpolator)r   r   r   r`   ra   r   r   r]   r   r   
compute_dzr[   rw   )r   r   kwargsr   r   r   r     s    
z_DOF_estimator.__init__c                 K   s   t d S rF   r=   )r   r   r   r   r   r     s    z_DOF_estimator.compute_dzc                 C   s6   t | j}| j| j }| j| j }| |||}|S )zU
        Compute reduced-HCT elements degrees of freedom, from the gradient.
        )r   rm   ra   r   r]   r[   get_dof_vec)r   rs   tri_ztri_dzZtri_dofr   r   r   rw     s
    z"_DOF_estimator.compute_dof_from_dfc                 C   sh  | j d }tj|dgtjd}tj| }tj| }|tj|dddddf dd }|tj|dddddf dd }|tj|dddddf dd }	t|ddddf |ddddf |	ddddf g|ddddf |ddddf |	ddddf gg}
| |ddddd	f< |
dddf |dddd
d	f< |
dddf |ddddd	f< |S )a\  
        Compute the dof vector of a triangle, from the value of f, df and
        of the local Jacobian at each node.

        Parameters
        ----------
        tri_z : shape (3,) array
            f nodal values.
        tri_dz : shape (3, 2) array
            df/dx, df/dy nodal values.
        J
            Jacobian matrix in local basis of apex 0.

        Returns
        -------
        dof : shape (9,) array
            For each apex ``iapex``::

                dof[iapex*3+0] = f(Ai)
                dof[iapex*3+1] = df(Ai).(AiAi+)
                dof[iapex*3+2] = df(Ai).(AiAi-)
        r   r   r    Nr$   rh   r#   r   r   r   )	r   r   r   r)   rf   r   r   rk   r|   )r   r   rs   nptrr   r   r   Zcol0Zcol1Zcol2r   r   r   r   r     s    


$$$22""z_DOF_estimator.get_dof_vecN)	r@   rA   rB   rC   r   r   rw   r   r   r   r   r   r   r     s   	
r   c                   @   s   e Zd ZdZdd ZdS )rt   z3dz is imposed by user; accounts for scaling if any.c                 C   s,   |\}}|| j  }|| j }t||gjS rF   )r   r   r   vstackT)r   r[   r&   r'   r   r   r   r   (  s    

z_DOF_estimator_user.compute_dzN)r@   rA   rB   rC   r   r   r   r   r   rt   %  s   rt   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	ru   z=Fast 'geometric' approximation, recommended for large arrays.c                 C   s   |   }|  }tjt| jt|d}t|}t|}tdD ]\}|dd|f |dddf  |dd|f< |dd|f |dddf  |dd|f< qHtjt| jt|d}tjt| jt|d}|| }	|| }
t|	|
gj	S )a  
        self.df is computed as weighted average of _triangles sharing a common
        node. On each triangle itri f is first assumed linear (= ~f), which
        allows to compute d~f[itri]
        Then the following approximation of df nodal values is then proposed:
            f[ipt] = SUM ( w[itri] x d~f[itri] , for itri sharing apex ipt)
        The weighted coeff. w[itri] are proportional to the angle of the
        triangle itri at apex ipt
        r   r   Nr   r#   )
compute_geom_weightscompute_geom_gradsr   r   r+   r]   
empty_liker   r   r   )r   Z	el_geom_wZel_geom_gradZ
w_node_sumZdfx_el_wZdfy_el_wZiapexZdfx_node_sumZdfy_node_sumZ	dfx_estimZ	dfy_estimr   r   r   r   2  s&    


,.z_DOF_estimator_geom.compute_dzc           
      C   sF  t t | jddg}| j}tdD ]}|dd|d ddf }|dd|d d ddf }|dd|d d ddf }t |dddf |dddf  |dddf |dddf  }t |dddf |dddf  |dddf |dddf  }t || t j d }	dt |	d  |dd|f< q&|S )z
        Build the (nelems, 3) weights coeffs of _triangles angles,
        renormalized so that np.sum(weights, axis=1) == np.ones(nelems)
        r   r   Nr#   r   )	r   r   r,   r]   ra   r   arctan2abspi)
r   r   ro   Ziptp0p1p2Zalpha1Zalpha2angler   r   r   r   S  s    DD z(_DOF_estimator_geom.compute_geom_weightsc                 C   s~  | j }| j| j }|dddddf |dddddf  }|dddddf |dddddf  }t||g}t|}|dddf |dddf  }|dddf |dddf  }t||gj}	t|	}
|	dddf |ddddf  |	dddf |ddddf   |
dddf< |	dddf |ddddf  |	dddf |ddddf   |
dddf< |
S )z
        Compute the (global) gradient component of f assumed linear (~f).
        returns array df of shape (nelems, 2)
        df[ielem].dM[ielem] = dz[ielem] i.e. df = dz x dM = dM.T^-1 x dz
        Nr#   r   r$   )	ra   r   r]   r   dstackr   r   r   r   )r   ro   Ztris_fZdM1ZdM2ZdMZdM_invZdZ1ZdZ2ZdZdfr   r   r   r   i  s    ,,  
PPz&_DOF_estimator_geom.compute_geom_gradsN)r@   rA   rB   rC   r   r   r   r   r   r   r   ru   /  s   !ru   c                       s,   e Zd ZdZ fddZ fddZ  ZS )rv   z
    The 'smoothest' approximation, df is computed through global minimization
    of the bending energy:
      E(f) = integral[(d2z/dx2 + d2z/dy2 + 2 d2z/dxdy)**2 dA]
    c                    s   |j | _ t | d S rF   )rc   rG   r   )r   ZInterpolatorrJ   r   r   r     s    z_DOF_estimator_min_E.__init__c                    s  t   }t|}t }t| j}| j}| j	}| j
| j	 }|||||\}}	}
}d}|jd }t|
||	||fd}|  t||||d\}}tj||| }||k rtd |}tj| jjd dgtjd}|ddd |dddf< |d	dd |ddd	f< |S )
z{
        Elliptic solver for bending energy minimization.
        Uses a dedicated 'toy' sparse Jacobi PCG solver.
        绽|=r   )r   )Ar~   x0tolzIn TriCubicInterpolator initialization, PCG sparse solver did not converge after 1000 iterations. `geom` approximation is used instead of `min_E`r$   r    Nr#   )rG   r   r   r+   rf   r   rm   ra   rc   r]   r   r   r   _Sparse_Matrix_coocompress_csc_cglinalgnormdotr   warn_externalr.   r`   r)   )r   Zdz_initZUf0Zreference_elementrs   Zeccsr   r   r   r   r   r   r   Zn_dofZKff_cooZUfr:   Zerr0r[   rJ   r   r   r     s2    



z_DOF_estimator_min_E.compute_dz)r@   rA   rB   rC   r   r   rU   r   r   rJ   r   rv     s   rv   c                   @   sH   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Ze	dd Z
dS )r   c                 C   sF   |\| _ | _tj|tjd| _tj|tjd| _tj|tjd| _dS )a4  
        Create a sparse matrix in coo format.
        *vals*: arrays of values of non-null entries of the matrix
        *rows*: int arrays of rows of non-null entries of the matrix
        *cols*: int arrays of cols of non-null entries of the matrix
        *shape*: 2-tuple (n, m) of matrix shape
        r    N)	r   mr   r   r)   valsr   rowscols)r   r   r   r  r   r   r   r   r     s    z_Sparse_Matrix_coo.__init__c                 C   s2   |j | jfksJ tj| j| j|| j  | jdS )z
        Dot product of self by a vector *V* in sparse-dense to dense format
        *V* dense vector of shape (self.m,).
        )r   	minlength)r   r   r   r   r   r   r  )r   r   r   r   r   r     s
    z_Sparse_Matrix_coo.dotc                 C   sR   t j| j| j| j  ddd\}}}| j| | _| j| | _t j|| jd| _dS )zV
        Compress rows, cols, vals / summing duplicates. Sort for csc format.
        Tr9   return_inverser   N)r   uniquer   r   r  r   r   r   _r  indicesr   r   r   r     s    z_Sparse_Matrix_coo.compress_cscc                 C   sR   t j| j| j | j ddd\}}}| j| | _| j| | _t j|| jd| _dS )zV
        Compress rows, cols, vals / summing duplicates. Sort for csr format.
        Tr  r   N)r   r  r   r   r  r   r   r  r   r   r   compress_csr  s    z_Sparse_Matrix_coo.compress_csrc                 C   sX   t j| j| jgt jd}| jj}t|D ]*}|| j| | j	| f  | j| 7  < q(|S )zY
        Return a dense matrix representing self, mainly for debugging purposes.
        r    )
r   r   r   r   r)   r   r,   r   r   r  )r   r7   nvalsir   r   r   to_dense  s
    (z_Sparse_Matrix_coo.to_densec                 C   s   |    S rF   )r  __str__)r   r   r   r   r    s    z_Sparse_Matrix_coo.__str__c                 C   s>   | j | jk}tjt| j| jtjd}| j| || j | < |S )z3Return the (dense) vector of the diagonal elements.r    )r   r  r   r   minr   r)   r   )r   Zin_diagdiagr   r   r   r    s    z_Sparse_Matrix_coo.diagN)r@   rA   rB   r   r   r   r	  r  r  propertyr  r   r   r   r   r     s   

r   r     c                 C   s4  |j }| j|ksJ | j|ks"J tj|}| j}t|d}|du rTt|}n|}|| 	| }	|	| }
t|}d}t	|	|
}d}t
t||| kr||k r|
||  }| 	|}|t	|| }|	||  }	|	| }
|}t	|	|
}|||  }|| }|d7 }qtj| 	|| }||fS )a  
    Use Preconditioned Conjugate Gradient iteration to solve A x = b
    A simple Jacobi (diagonal) preconditioner is used.

    Parameters
    ----------
    A : _Sparse_Matrix_coo
        *A* must have been compressed before by compress_csc or
        compress_csr method.
    b : array
        Right hand side of the linear system.
    x0 : array, optional
        Starting guess for the solution. Defaults to the zero vector.
    tol : float, optional
        Tolerance to achieve. The algorithm terminates when the relative
        residual is below tol. Default is 1e-10.
    maxiter : int, optional
        Maximum number of iterations.  Iteration will stop after *maxiter*
        steps even if the specified tolerance has not been achieved. Defaults
        to 1000.

    Returns
    -------
    x : array
        The converged solution.
    err : float
        The absolute error np.linalg.norm(A.dot(x) - b)
    gư>Nr   r   r#   )r,   r   r   r   r   r   r  maximumr   r   sqrtr   )r   r~   r   r   maxiterr   Zb_normZkvecr   rwpbetarhokr   rp   Zrhooldr:   r   r   r   r     s8    
"

r   c                 C   sH  t jd| d t| }| ddddf | ddddf  }|| ddddf | ddddf   }t|dt| k}t|rd| }n t| jd }d||  ||< | ddddf | |ddddf< | ddddf  | |ddddf< | ddddf  | |ddddf< | ddddf | |ddddf< |S )z
    Inversion of arrays of (2, 2) matrices, returns 0 for rank-deficient
    matrices.

    *M* : array of (2, 2) matrices to inverse, shape (n, 2, 2)
    Nr$   r$   r   Nr   r#   :0yE>r   )r   check_shaper   r   r   allr   r   )r   M_invprod1deltarank2Z	delta_invr   r   r   r   w  s    
$(

$&&$r   c           	      C   sT  t jd| d t| }| ddddf | ddddf  }|| ddddf | ddddf   }t|dt| k}t|r | ddddf | |ddddf< | ddddf  | |ddddf< | ddddf  | |ddddf< | ddddf | |ddddf< n0|| }| |ddf | ||ddf< | |ddf  | ||ddf< | |ddf  | ||ddf< | |ddf | ||ddf< | }| |ddf | |ddf  }t|dk }d| |d |  }| |ddf | ||ddf< | |ddf | ||ddf< | |ddf | ||ddf< | |ddf | ||ddf< |S )	a  
    Inversion of arrays of (2, 2) SYMMETRIC matrices; returns the
    (Moore-Penrose) pseudo-inverse for rank-deficient matrices.

    In case M is of rank 1, we have M = trace(M) x P where P is the orthogonal
    projection on Im(M), and we return trace(M)^-1 x P == M / trace(M)**2
    In case M is of rank 0, we return the null matrix.

    *M* : array of (2, 2) matrices to inverse, shape (n, 2, 2)
    r  r  Nr   r#   r  r   r$   )r   r  r   r   r   r  )	r   r   r!  r"  r#  Zrank01trZtr_zerosZ	sq_tr_invr   r   r   r{     s0    
$($&&(r{   c                 C   s   | ddt jt jf | S )z6
    Scalar product between scalars and matrices.
    N)r   newaxis)scalarr   r   r   r   r     s    r   c                 C   s   t | g dS )z4
    Transposition of an array of matrices *M*.
    )r   r$   r#   )r   	transposer  r   r   r   rz     s    rz   c                 C   s  |dv sJ | j }|dksJ |j }|dks0J | j}|dd \}}|d |jd ks\J tj|d tjd}t| }	|dkrt|D ]8}
t|D ]*}| || |
 | |f |	dd|
|f< qqnBt|D ]8}
t|D ]*}| ||
| | | f |	dd|
|f< qq|	S )z{
    Roll an array of matrices along *axis* (0: rows, 1: columns) according to
    an array of indices *roll_indices*.
    r   r#   r   r#   Nr   r    )rx   r   r   r   r   r   r   )r   Zroll_indicesri   rx   Z	ndim_rollshr  r   Zvec_indicesZM_rolliricr   r   r   r     s$    
,*r   c           
      C   s   t | ttfsJ tdd | D s(J tdd | D }t||d  dksVJ t| }|d }t| d d }|j}|jd ||g}tj	||d}t
|D ]2}t
|D ]$}	t| | |	 |dd||	f< qq|S )a+  
    Build an array of matrices from individuals np.arrays of identical shapes.

    Parameters
    ----------
    M
        ncols-list of nrows-lists of shape sh.

    Returns
    -------
    M_res : np.array of shape (sh, nrow, ncols)
        *M_res* satisfies ``M_res[..., i, j] = M[i][j]``.
    c                 s   s   | ]}t |ttfV  qd S rF   )
isinstancetuplelist.0itemr   r   r   	<genexpr>      z(_to_matrix_vectorized.<locals>.<genexpr>c                 S   s   g | ]}t |qS r   )lenr0  r   r   r   
<listcomp>  r4  z)_to_matrix_vectorized.<locals>.<listcomp>r   r    N)r-  r.  r/  r  r   r   r5  r!   r   r.   r   )
r   Zc_vecr  r   ZM00dtr*  ZM_retZirowicolr   r   r   r|     s    $r|   c                 C   s   |j dksJ |dv sJ | j\}}|dkr>|jd ||g}n|jd ||g}| j}tj||d}|dkrt|D ].}	| || |	 ddf |dd|	ddf< qrn8t|D ].}
| dd|| |
 f |dddd|
f< q|S )z
    Extract selected blocks of a matrices *M* depending on parameters
    *block_indices* and *block_size*.

    Returns the array of extracted matrices *Mres* so that ::

        M_res[..., ir, :] = M[(block_indices*block_size+ir), :]
    r#   r(  r   r    N)rx   r   r!   r   r.   r   )r   Zblock_indicesr   ri   r  r   r*  r7  ZM_resr+  r,  r   r   r   r     s    	
.,r   )Nr   r  )rC   numpyr   
matplotlibr   matplotlib.trir   matplotlib.tri.trifinderr   Zmatplotlib.tri.tritoolsr   __all__r   r   r   rf   r   rt   ru   rv   r   r   r   r{   r   rz   r   r|   r   r   r   r   r   <module>   s:    Z6  &   L
U;D
t.