o
    i6                     @   s   d dl 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 dl	m
Z
 d dlmZ 		ddd	Z		dd
dZ		dddZdd Zdd Zdd ZdS )    N)cublas)_dtype)device)_csr)
_interfaceh㈵>c                 C   st  t | |||\} }}}| j}	|j}
| jd }|du r|d }|dkr)t|dfS tj|}|dkr7|dfS |du rB|t| }ntt||t| }||	| }d}d}||k r|
|}|}t	
||}|dkrn|}n
|| }|||  }|	|}|t	
|| }|||  }|||  }|d7 }|dur|| t	|}||krn||k s[d}||kr||ks|}||fS )a  Uses Conjugate Gradient iteration to solve ``Ax = b``.

    Args:
        A (ndarray, spmatrix or LinearOperator): The real or complex matrix of
            the linear system with shape ``(n, n)``. ``A`` must be a hermitian,
            positive definitive matrix with type of :class:`cupy.ndarray`,
            :class:`cupyx.scipy.sparse.spmatrix` or
            :class:`cupyx.scipy.sparse.linalg.LinearOperator`.
        b (cupy.ndarray): Right hand side of the linear system with shape
            ``(n,)`` or ``(n, 1)``.
        x0 (cupy.ndarray): Starting guess for the solution.
        tol (float): Tolerance for convergence.
        maxiter (int): Maximum number of iterations.
        M (ndarray, spmatrix or LinearOperator): Preconditioner for ``A``.
            The preconditioner should approximate the inverse of ``A``.
            ``M`` must be :class:`cupy.ndarray`,
            :class:`cupyx.scipy.sparse.spmatrix` or
            :class:`cupyx.scipy.sparse.linalg.LinearOperator`.
        callback (function): User-specified function to call after each
            iteration. It is called as ``callback(xk)``, where ``xk`` is the
            current solution vector.
        atol (float): Tolerance for convergence.

    Returns:
        tuple:
            It returns ``x`` (cupy.ndarray) and ``info`` (int) where ``x`` is
            the converged solution and ``info`` provides convergence
            information.

    .. seealso:: :func:`scipy.sparse.linalg.cg`
    r   N
      )_make_systemmatvecshapecupy
empty_likelinalgnormfloatmaxr   dotcnrm2)Abx0tolmaxiterMcallbackatolxr   psolvenb_normritersrhozrho1pbetaqalpharesidinfo r,   a/home/ubuntu/veenaModal/venv/lib/python3.10/site-packages/cupyx/scipy/sparse/linalg/_iterative.pycg   sP   !

r.   c
                 C   s  t | |||\} }}
}| j}|j}| jd }|dkr!t|dfS tj|}|dkr/|dfS |du r:|t| }ntt||t| }|du rM|d }|du rSd}t	||}|	du r^d}	|	dvrit
d|	|du rod}	tj||f| jdd	}tj|d
 |f| jdd	}tj|d
 f| jd}t|}d}	 ||
}||| }t|}|	dkr|| n|	dkr|dkr|||  ||ks||krnr|| }||dddf< ||d< t|D ]A}||}||}|||\|d|d
 |f< }tj|||d
 |f d |d
 |k r|||d
 |f  }||dd|d
 f< qtjt||}t|d }|
|| 7 }
||7 }qd}||krH||ksH|}||fS )a  Uses Generalized Minimal RESidual iteration to solve ``Ax = b``.

    Args:
        A (ndarray, spmatrix or LinearOperator): The real or complex
            matrix of the linear system with shape ``(n, n)``. ``A`` must be
            :class:`cupy.ndarray`, :class:`cupyx.scipy.sparse.spmatrix` or
            :class:`cupyx.scipy.sparse.linalg.LinearOperator`.
        b (cupy.ndarray): Right hand side of the linear system with shape
            ``(n,)`` or ``(n, 1)``.
        x0 (cupy.ndarray): Starting guess for the solution.
        tol (float): Tolerance for convergence.
        restart (int): Number of iterations between restarts. Larger values
            increase iteration cost, but may be necessary for convergence.
        maxiter (int): Maximum number of iterations.
        M (ndarray, spmatrix or LinearOperator): Preconditioner for ``A``.
            The preconditioner should approximate the inverse of ``A``.
            ``M`` must be :class:`cupy.ndarray`,
            :class:`cupyx.scipy.sparse.spmatrix` or
            :class:`cupyx.scipy.sparse.linalg.LinearOperator`.
        callback (function): User-specified function to call on every restart.
            It is called as ``callback(arg)``, where ``arg`` is selected by
            ``callback_type``.
        callback_type (str): 'x' or 'pr_norm'. If 'x', the current solution
            vector is used as an argument of callback function. if 'pr_norm',
            relative (preconditioned) residual norm is used as an argument.
        atol (float): Tolerance for convergence.

    Returns:
        tuple:
            It returns ``x`` (cupy.ndarray) and ``info`` (int) where ``x`` is
            the converged solution and ``info`` provides convergence
            information.

    Reference:
        M. Wang, H. Klie, M. Parashar and H. Sudan, "Solving Sparse Linear
        Systems on NVIDIA Tesla GPUs", ICCS 2009 (2009).

    .. seealso:: :func:`scipy.sparse.linalg.gmres`
    r   Nr      pr_norm)r   r0   zUnknown callback_type: {}F)dtypeorderr	   r2   Tr   )out)r
   r   r   r   r   r   r   r   r   min
ValueErrorformatemptyr2   zerosnumpy_make_compute_hur   r   rangelstsqasnumpyarray)r   r   r   r   restartr   r   r   r   callback_typer   r   r   r   r    VHe
compute_hur"   mxr!   r_normvjr$   uretyr+   r,   r,   r-   gmres\   sv   )



rN   c                 C   s  t | |||\} }}}| j}	|j}
| jd }|dkr!t|dfS tj|}|dkr/|dfS |du r:|t| }ntt||t| }|du rM|d }||	| }t	||}|
 }|}|
 }d}	 |
|}|	|}t	||}|| }|||  }|
|| }||| 7 }|	|}||| 8 }tj|}|d7 }|dur|| ||ks||krn#t	||}|| }|}|||  }||9 }||7 }||9 }||7 }qfd}||kr||k s|}||fS )a  Use Conjugate Gradient Squared iteration to solve ``Ax = b``.

    Args:
        A (ndarray, spmatrix or LinearOperator): The real or complex matrix of
            the linear system with shape ``(n, n)``.
        b (cupy.ndarray): Right hand side of the linear system with shape
            ``(n,)`` or ``(n, 1)``.
        x0 (cupy.ndarray): Starting guess for the solution.
        tol (float): Tolerance for convergence.
        maxiter (int): Maximum number of iterations.
        M (ndarray, spmatrix or LinearOperator): Preconditioner for ``A``.
            The preconditioner should approximate the inverse of ``A``.
            ``M`` must be :class:`cupy.ndarray`,
            :class:`cupyx.scipy.sparse.spmatrix` or
            :class:`cupyx.scipy.sparse.linalg.LinearOperator`.
        callback (function): User-specified function to call after each
            iteration. It is called as ``callback(xk)``, where ``xk`` is the
            current solution vector.
        atol (float): Tolerance for convergence.

    Returns:
        tuple:
            It returns ``x`` (cupy.ndarray) and ``info`` (int) where ``x`` is
            the converged solution and ``info`` provides convergence
            information.

    .. seealso:: :func:`scipy.sparse.linalg.cgs`
    r   N   Tr	   )r
   r   r   r   r   r   r   r   r   dotcopy)r   r   r   r   r   r   r   r   r   r   r   r   r    r0r#   r!   rK   r&   r"   rM   rI   sigmar)   r(   r$   AzrH   rho_newr'   r+   r,   r,   r-   cgs   sb   
rV   c                 C   sj  t | }t| } |durtj| j|| j| jd} | jd | jd kr+td| j| jj	dvr9t
d| j| jd }|j|fksO|j|dfksOtd|| j }|du retj|f| jd	}n|j|fksv|j|dfksvtd
|| j }|du rtj| j| jd}n#t |}t|}|durtj|j||j|jd}| j|jkrtd| |||fS )a  Make a linear system Ax = b

    Args:
        A (cupy.ndarray or cupyx.scipy.sparse.spmatrix or
            cupyx.scipy.sparse.LinearOperator): sparse or dense matrix.
        M (cupy.ndarray or cupyx.scipy.sparse.spmatrix or
            cupyx.scipy.sparse.LinearOperator): preconditioner.
        x0 (cupy.ndarray): initial guess to iterative method.
        b (cupy.ndarray): right hand side.

    Returns:
        tuple:
            It returns (A, M, x, b).
            A (LinaerOperator): matrix of linear system
            M (LinearOperator): preconditioner
            x (cupy.ndarray): initial guess
            b (cupy.ndarray): right hand side.
    N)r   rmatvecr2   r   r	   z"expected square matrix (shape: {})fdFDzunsupprted dtype (actual: {})zb has incompatible dimensionsr4   zx0 has incompatible dimensions)r   r2   z/matrix and preconditioner have different shapes)_make_fast_matvecr   aslinearoperatorLinearOperatorr   rW   r2   r7   r8   char	TypeErrorastyperavelr   r:   IdentityOperator)r   r   r   r   fast_matvecr   r   r,   r,   r-   r
   +  s<   




r
   c                    s   ddl m  ddlm t| rdrt  j	t	
d| jt	
d| jt| j jtj| jd f| jd}tj| jd f| jd}j| j|}j|} 	jjj|jjj|j	}t|tj~~~~ 	f
dd}|S d S )	Nr   )cusparsespmv      ?        r4   c                    sT   t | }j| }j|} 	jjj|jjj|jjj
 |S )N)	r   r   DnVecDescriptorcreatespMVctypesdatadescptr)r   rM   desc_xdesc_y
	_cusparsealgr)   r'   buff
cuda_dtyperb   desc_Ahandleop_ar,   r-   r   t  s   
z!_make_fast_matvec.<locals>.matvec)cupy_backends.cuda.libsrb   cupyxr   isspmatrix_csrcheck_availabilityr   get_cusparse_handle CUSPARSE_OPERATION_NON_TRANSPOSEr;   r@   r2   r   to_cuda_dtypeCUSPARSE_MV_ALG_DEFAULTr   r9   r   SpMatDescriptorrg   rf   spMV_bufferSizeri   rj   rk   int8)r   r   rM   rm   rn   	buff_sizer   r,   ro   r-   rY   ^  s.   	rY   c                    s   t   jjdkrtjn jjdkrtjn jjdkr"tjn	 jjdkr+tj j	d t
d jt
d jt
d j fd	d
}|S )Nfdr1   Dr   rd   re   g      c                    s   t j|d f jd}tj|d jj jj| jjdjj|jjd tj|d jj jj|jjdjj| jjd || fS )Nr	   r4   )	r   r9   r2   _cublasCUBLAS_OP_Cri   rj   rl   CUBLAS_OP_N)rK   rJ   hrC   gemvru   moner   onezeror,   r-   rF     s   z$_make_compute_hu.<locals>.compute_hu)r   get_cublas_handler2   r\   r   sgemvdgemvcgemvzgemvr   r;   r@   )rC   rF   r,   r   r-   r<     s   
	r<   )Nr   NNNN)Nr   NNNNNN)r;   r   r   
cupy._corer   	cupy.cudar   rw   r   cupyx.scipy.sparser   cupyx.scipy.sparse.linalgr   r.   rN   rV   r
   rY   r<   r,   r,   r,   r-   <module>   s(    
P
o
`3#