
    _-Pho                         d Z ddlmZ ddlZddlmZ ddlmc m	Z
 ddlm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  G d d          Zd Z G d de          ZdS )zGeneric AMG solver.    )warnNpinv)LinearOperator   )krylov)to_type)set_tol)	smoothing)upcastc                       e Zd ZdZ G d d          Z G d de          ZddZd Zdd
Zd Z	d Z
d Zd ZddZ	 	 ddZddZdS )MultilevelSolvera  Stores multigrid hierarchy and implements the multigrid cycle.

    The class constructs the cycling process and points to the methods for
    coarse grid solves.  A MultilevelSolver object is typically returned from a
    particular AMG method (see ruge_stuben_solver or smoothed_aggregation_solver
    for example).  A call to MultilevelSolver.solve() is a typical access
    point.  The class also defines methods for constructing operator, cycle, and
    grid complexities.

    Attributes
    ----------
    levels : level array
        Array of level objects that contain A, R, and P.
    coarse_solver : string
        String passed to coarse_grid_solver indicating the solve type

    Methods
    -------
    aspreconditioner()
        Create a preconditioner using this multigrid cycle
    cycle_complexity()
        A measure of the cost of a single multigrid cycle.
    grid_complexity()
        A measure of the rate of coarsening.
    operator_complexity()
        A measure of the size of the multigrid hierarchy.
    solve()
        Iteratively solves a linear system for the right hand side.
    change_solve_matrix(A)
        Change matrix solve/preconditioning matrix.
        This also changes the corresponding relaxation routines on the fine
        grid.  This can be used, for example, to precondition a
        quadratic finite element discretization with AMG built from
        a linear discretization on quadratic quadrature points.
    c                       e Zd ZdZd ZdS )MultilevelSolver.Levela  Stores one level of the multigrid hierarchy.

        All level objects will have an 'A' attribute referencing the matrix
        of that level.  All levels, except for the coarsest level, will
        also have 'P' and 'R' attributes referencing the prolongation and
        restriction operators that act between each level and the next
        coarser level.

        Attributes
        ----------
        A : csr_matrix
            Problem matrix for Ax=b
        R : csr_matrix
            Restriction matrix between levels (often R = P.T)
        P : csr_matrix
            Prolongation or Interpolation matrix.

        Notes
        -----
        The functionality of this class is a struct

        c                     d| _         dS )zLevel construct (empty).N)Aselfs    P/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/pyamg/multilevel.py__init__zMultilevelSolver.Level.__init__N   s    DFFF    N)__name__
__module____qualname____doc__r    r   r   Levelr   6   s-        	 	.	 	 	 	 	r   r   c                   "     e Zd ZdZ fdZ xZS )MultilevelSolver.levelzDeprecated level class.c                 v    t                                                       t          dt          d           dS )-Raise deprecation warning on use, not import.z#level() is deprecated.  use Level()   category
stacklevelNsuperr   r   DeprecationWarning)r   	__class__s    r   r   zMultilevelSolver.level.__init__U   sB    GG6,< < < < < <r   r   r   r   r   r   __classcell__r)   s   @r   levelr   R   s>        %%	< 	< 	< 	< 	< 	< 	< 	< 	<r   r-   r   c                     d| _         || _        t          |          | _        |dd         D ]5}t	          |d          s#|j        j                                        |_        6dS )a  Class constructor to initialize the cycle and ensure list of levels is complete.

        Parameters
        ----------
        levels : level array
            Array of level objects that contain A, R, and P.
        coarse_solver: string, callable, tuple
            The solver method is either (1) a string such as 'splu' or 'pinv'
            of a callable object which receives only parameters (A, b) and
            returns an (approximate or exact) solution to the linear system Ax
            = b, or (2) a callable object that takes parameters (A,b) and
            returns an (approximate or exact) solution to Ax = b, or (3) a
            tuple of the form (string|callable, args), where args is a
            dictionary of arguments to be passed to the function denoted by
            string or callable.

            Sparse direct methods:

            * splu         : sparse LU solver

            Sparse iterative methods:

            * any method in scipy.sparse.linalg or pyamg.krylov (e.g. 'cg').
            * Methods in pyamg.krylov take precedence.
            * relaxation method, such as 'gauss_seidel' or 'jacobi',

            Dense methods:

            * pinv     : pseudoinverse (SVD)
            * lu       : LU factorization
            * cholesky : Cholesky factorization

        Notes
        -----
        If not defined, the R attribute on each level is set to
        the transpose of P.

        Examples
        --------
        >>> # manual construction of a two-level AMG hierarchy
        >>> from pyamg.gallery import poisson
        >>> from pyamg.multilevel import MultilevelSolver
        >>> from pyamg.strength import classical_strength_of_connection
        >>> from pyamg.classical.interpolate import direct_interpolation
        >>> from pyamg.classical.split import RS
        >>> # compute necessary operators
        >>> A = poisson((100, 100), format='csr')
        >>> C = classical_strength_of_connection(A)
        >>> splitting = RS(A)
        >>> P = direct_interpolation(A, C, splitting)
        >>> R = P.T
        >>> # store first level data
        >>> levels = []
        >>> levels.append(MultilevelSolver.Level())
        >>> levels.append(MultilevelSolver.Level())
        >>> levels[0].A = A
        >>> levels[0].C = C
        >>> levels[0].splitting = splitting
        >>> levels[0].P = P
        >>> levels[0].R = R
        >>> # store second level data
        >>> levels[1].A = R @ A @ P                      # coarse-level matrix
        >>> # create MultilevelSolver
        >>> ml = MultilevelSolver(levels, coarse_solver='splu')
        >>> print(ml)
        MultilevelSolver
        Number of Levels:     2
        Operator Complexity:  1.891
        Grid Complexity:      1.500
        Coarse Solver:        'splu'
          level   unknowns     nonzeros
             0       10000        49600 [52.88%]
             1        5000        44202 [47.12%]
        <BLANKLINE>

        FNR)	symmetric_smoothinglevelscoarse_grid_solvercoarse_solverhasattrPT	conjugater0   )r   r2   r4   r-   s       r   r   zMultilevelSolver.__init__[   so    Z $) />>CRC[ 	0 	0E5#&& 0')--//	0 	0r   c           
         d}|dt          | j                   dz  }|d|                                 ddz  }|d|                                 ddz  }|d| j                                         dz  }t          d | j        D                       }|d	z  }t          | j                  D ]>\  }}|j        }d
|j	        z  |z  }||dd|j
        d         dd|j	        dd|ddz  }?|S )z5Print basic statistics about the multigrid hierarchy.zMultilevelSolver
zNumber of Levels:     
zOperator Complexity:  z6.3fzGrid Complexity:      zCoarse Solver:        c              3   .   K   | ]}|j         j        V  d S Nr   nnz.0r-   s     r   	<genexpr>z,MultilevelSolver.__repr__.<locals>.<genexpr>   s&      ========r   z   level   unknowns     nonzeros
d   z>6 r   z>11z>12z [z2.2fz%]
)lenr2   operator_complexitygrid_complexityr4   namesum	enumerater   r>   shape)r   output	total_nnznr-   r   ratios          r   __repr__zMultilevelSolver.__repr__   s=   %?3t{+;+;????N4+C+C+E+ENNNNNJ4+?+?+A+AJJJJJH4+=+B+B+D+DHHHH=======	 	55!$+.. 	O 	OHAuA!%K)+ENNN
NNNNNNeNNNNNFFr   Vc                 t    t          |                                          }d  j        D              fd fd fd|dk    r d          }n5|dv r d          }n%|dk    r d          }nt          d	| d
          t	          |          t	          d                   z  S )a  Cycle complexity of V, W, AMLI, and F(1,1) cycle with simple relaxation.

        Cycle complexity is an approximate measure of the number of
        floating point operations (FLOPs) required to perform a single
        multigrid cycle relative to the cost a single smoothing operation.

        Parameters
        ----------
        cycle : {'V','W','F','AMLI'}
            Type of multigrid cycle to perform in each iteration.

        Returns
        -------
        cc : float
            Defined as F_sum / F_0, where
            F_sum is the total number of nonzeros in the matrix on all
            levels encountered during a cycle and F_0 is the number of
            nonzeros in the matrix on the finest level.

        Notes
        -----
        This is only a rough estimate of the true cycle complexity. The
        estimate assumes that the cost of pre and post-smoothing are
        (each) equal to the number of nonzeros in the matrix on that level.
        This assumption holds for smoothers like Jacobi and Gauss-Seidel.
        However, the true cycle complexity of cycle using more expensive
        methods, like block Gauss-Seidel will be underestimated.

        Additionally, if the cycle used in practice isn't a (1,1)-cycle,
        then this cost estimate will be off.

        c                 &    g | ]}|j         j        S r   r=   r?   s     r   
<listcomp>z5MultilevelSolver.cycle_complexity.<locals>.<listcomp>   s    444uuw{444r   c                     t          j                  dk    rd         S | t          j                  dz
  k    rd|          z  | dz            z   S d|          z   | dz             z   S Nr   r   r"   rD   r2   )r-   rP   r>   r   s    r   rP   z,MultilevelSolver.cycle_complexity.<locals>.V   su    4;1$$1vDK((1,,,3u:~EAI66s5z>AAeaiLL00r   c                     t          j                  dk    rd         S | t          j                  dz
  k    rd|          z  | dz            z   S d|          z  d | dz             z  z   S rU   rV   )r-   Wr>   r   s    r   rX   z,MultilevelSolver.cycle_complexity.<locals>.W   sz    4;1$$1vDK((1,,,3u:~EAI66s5z>A%!)$444r   c                     t          j                  dk    rd         S | t          j                  dz
  k    rd|          z  | dz            z   S d|          z   | dz             z    | dz             z   S rU   rV   )r-   FrP   r>   r   s    r   rZ   z,MultilevelSolver.cycle_complexity.<locals>.F   s    4;1$$1vDK((1,,,3u:~EAI66s5z>AAeaiLL011UQY<<??r   rP   r   )rX   AMLIrZ   Unrecognized cycle type ())strupperr2   	TypeErrorfloat)r   cycleflopsrZ   rP   rX   r>   s   `  @@@@r   cycle_complexityz!MultilevelSolver.cycle_complexity   s-   B E

  ""44444	1 	1 	1 	1 	1 	1 	1	5 	5 	5 	5 	5 	5 	5	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ C<<AaDDEEm##AaDDEEc\\AaDDEE@@@@AAAU||eCFmm++r   c                     t          d | j        D                       t          | j        d         j        j                  z  S )zOperator complexity of this multigrid hierarchy.

        Defined as:
            Number of nonzeros in the matrix on all levels /
            Number of nonzeros in the matrix on the finest level

        c              3   .   K   | ]}|j         j        V  d S r<   r=   r?   s     r   rA   z7MultilevelSolver.operator_complexity.<locals>.<genexpr>  s&      88557;888888r   r   )rH   r2   ra   r   r>   r   s    r   rE   z$MultilevelSolver.operator_complexity  sA     88DK88888$+a."&''( 	(r   c                     t          d | j        D                       t          | j        d         j        j        d                   z  S )zGrid complexity of this multigrid hierarchy.

        Defined as:
            Number of unknowns on all levels /
            Number of unknowns on the finest level

        c              3   :   K   | ]}|j         j        d          V  dS )r   N)r   rJ   r?   s     r   rA   z3MultilevelSolver.grid_complexity.<locals>.<genexpr>"  s+      ==57=#======r   r   )rH   r2   ra   r   rJ   r   s    r   rF   z MultilevelSolver.grid_complexity  sF     =======$+a."(+,,- 	-r   c                 h    || j         d         _        t          j        | j         d                    dS )a|  Change matrix solve/preconditioning matrix.

        Parameters
        ----------
        A : csr_matrix
            Target solution matrix

        Notes
        -----
        This also changes the corresponding relaxation routines on the fine
        grid.  This can be used, for example, to precondition a
        quadratic finite element discretization with linears.
        r   N)r2   r   r   rebuild_smoother)r   r   s     r   change_solve_matrixz$MultilevelSolver.change_solve_matrix%  s/     A"4;q>22222r   c                 0    |                      |d          S )zLegacy solve interface.r   )maxitersolve)r   bs     r   psolvezMultilevelSolver.psolve7  s    zz!Qz'''r   c                       j         d         j        j        } j         d         j        j        } fd}t	          |||          S )a  Create a preconditioner using this multigrid cycle.

        Parameters
        ----------
        cycle : {'V','W','F','AMLI'}
            Type of multigrid cycle to perform in each iteration.

        Returns
        -------
        precond : LinearOperator
            Preconditioner suitable for the iterative solvers in defined in
            the scipy.sparse.linalg module (e.g. cg, gmres) and any other
            solver that uses the LinearOperator interface.  Refer to the
            LinearOperator documentation in scipy.sparse.linalg

        See Also
        --------
        MultilevelSolver.solve, scipy.sparse.linalg.LinearOperator

        Examples
        --------
        >>> from pyamg.aggregation import smoothed_aggregation_solver
        >>> from pyamg.gallery import poisson
        >>> from scipy.sparse.linalg import cg
        >>> import scipy as sp
        >>> A = poisson((100, 100), format='csr')          # matrix
        >>> b = np.random.rand(A.shape[0])                 # random RHS
        >>> ml = smoothed_aggregation_solver(A)            # AMG solver
        >>> M = ml.aspreconditioner(cycle='V')             # preconditioner
        >>> x, info = cg(A, b, tol=1e-8, maxiter=30, M=M)  # solve with CG

        r   c                 6                         | dd          S )Nr   g-q=)rm   rb   tolrn   )rp   rb   r   s    r   matvecz1MultilevelSolver.aspreconditioner.<locals>.matvec_  s    ::a%U:CCCr   dtype)r2   r   rJ   rw   r   )r   rb   rJ   rw   ru   s   ``   r   aspreconditionerz!MultilevelSolver.aspreconditioner;  sd    B A &A &	D 	D 	D 	D 	D 	D eV59999r   Nh㈵>rB   r   Fc           
      f   |t          j                  }nt          j        |          }| j        d         j        t          |                                          }|dk    r*t          d          rj        dk    rt          d          |1|dk    r| j
        st          d           |d	k    r|dk    rt          d
          i }t          |t
                    rBi }t          t          |          rt          t          |          }nt          t          |          }|                     |          }	  |f||||d|\  }}|
r||fS |S # t"          $ ra 4t           j                            |z  z
            gdd<   fd}n}||d<   d|d<    |f||||d|\  }}|
r||fcY S |cY S w xY wt           j                                      }|dk    rd}t           j                            |z  z
            }|gdd<   t)          j        |j        j                  }t-          ||g          \  }t          j                  t          j        |          }d}	 t1          | j                  dk    r|                               }n|                     d|||	           |dz  }t           j                            |z  z
            }                    |            |           |||z  k     r|
r|dfS |S ||k    r|
r||fS |S )a	  Execute multigrid cycling.

        Parameters
        ----------
        b : array
            Right hand side.
        x0 : array
            Initial guess.
        tol : float
            Stopping criteria: relative residual r[k]/||b|| tolerance.
            If `accel` is used, the stopping criteria is set by the Krylov method.
        maxiter : int
            Stopping criteria: maximum number of allowable iterations.
        cycle : {'V','W','F','AMLI'}
            Type of multigrid cycle to perform in each iteration.
        accel : string, function
            Defines acceleration method.  Can be a string such as 'cg'
            or 'gmres' which is the name of an iterative solver in
            pyamg.krylov (preferred) or scipy.sparse.linalg.
            If accel is not a string, it will be treated like a function
            with the same interface provided by the iterative solvers in SciPy.
        callback : function
            User-defined function called after each iteration.  It is
            called as callback(xk) where xk is the k-th iterate vector.
        residuals : list
            List to contain residual norms at each iteration.  The residuals
            will be the residuals from the Krylov iteration -- see the `accel`
            method to see verify whether this ||r|| or ||Mr|| (as in the case of
            GMRES).
        cycles_per_level: int, default 1
            Number of V-cycles on each level of an F-cycle
        return_info : bool
            If true, will return (x, info)
            If false, will return x (default)

        Returns
        -------
        x : array
            Approximate solution to Ax=b after k iterations

        info : string
            Halting status

            ==  =======================================
            0   successful exit
            >0  convergence to tolerance not achieved,
                return iteration count instead.
            ==  =======================================

        See Also
        --------
        aspreconditioner

        Examples
        --------
        >>> from numpy import ones
        >>> from pyamg import ruge_stuben_solver
        >>> from pyamg.gallery import poisson
        >>> A = poisson((100, 100), format='csr')
        >>> b = A * ones(A.shape[0])
        >>> ml = ruge_stuben_solver(A, max_coarse=10)
        >>> residuals = []
        >>> x = ml.solve(b, tol=1e-12, residuals=residuals) # standalone solver

        Nr   r[   symmetry	hermitianz@AMLI cycles require                     symmetry to be hermitiancgzIncompatible non-symmetric multigrid preconditioner detected, due to presmoother/postsmoother combination. CG requires SPD preconditioner, not just SPD matrix.fgmreszIAMLI cycles require acceleration (accel) to be fgmres, or no acceleration)rb   )x0rt   rm   Mcallback	residualsc                     t          j        |           r                    |            n8                    t           j                            | z  z
                        |            d S d S r<   )npisscalarappendlinalgnorm)xr   rp   r   r   s    r   callback_wrapperz0MultilevelSolver.solve.<locals>.callback_wrapper  st    ;q>> H%,,Q////%,,RY^^AAI-F-FGGG#/$HQKKKKK 0/r   rtolatol)r   rm   r   r   g        g      ?Tr   )r   
zeros_likearrayr2   r   r^   r_   r5   r{   
ValueErrorr1   r   
isinstancer   getattrslarx   r`   r   r   r   rw   r	   ravelrD   r4   _MultilevelSolver__solver   )r   rp   r   rt   rm   rb   accelr   r   cycles_per_levelreturn_infor   kwargsr   infor   normbnormrtpitr   s    `     ``           @r   ro   zMultilevelSolver.solved  s$   F :a  AAAKNE

  "" VOOJ!7!7Oz[((  ". / / /  (@ L M M M
 !!  "D E E E F%%% 065)) 0#FE22EE#C//E%%E%22A %1 Rg)1YR RJPR R4 #d7N   
 ($&INN1q1u9$=$=#>IaaaL( ( ( ( ( ( ( ( ( (0$ "%v!"v%1 EW)9E E=CE E4 #d7NNN5> INN1%%E|| 	q1q5y)) !7IaaaL AGQWag..aV$$AHQKKHQKK	4;1$$&&q!,,Q1e-=>>>!GBINN1q1u9--E$  '''#sU{""  a4KW}} !b5L1	s   =E E A$G?GGc                    | j         |         j        }| j         |                             |||           |||z  z
  }| j         |         j        |z  }t	          j        |          }	|t          | j                   dz
  k    r-|                     | j         d         j        |          |	dd<   n|dk    r|                     |dz   |	|d           n|dk    r8|                     |dz   |	||           |                     |dz   |	||           n|dk    rM|                     |dz   |	|||           t          d|          D ]}
|                     |dz   |	|dd           n\|d	k    rBd}| j         |dz            j        }t	          j
        ||j        d         f|j        
          }t	          j
        ||f|j        
          }t          |          D ]}d||ddf<   |                     |dz   ||ddf                             |j                  ||           t          |          D ]}t	          j        ||ddf                                         |||ddf         z            t	          j        ||ddf                                         |||ddf         z            z  |||f<   ||ddfxx         |||f         ||ddf         z  z  cc<   |||ddf         z  }t	          j        ||ddf                                         t	          j        |                    t	          j        ||ddf                                         |          z  }|	|||ddf                             |	j                  z  z  }	|||                    |j                  z  z  }nt#          d| d          || j         |         j        |	z  z  }| j         |                             |||           dS )a  Multigrid cycling.

        Parameters
        ----------
        lvl : int
            Solve problem on level `lvl`
        x : numpy array
            Initial guess `x` and return correction
        b : numpy array
            Right-hand side for Ax=b
        cycle : {'V','W','F','AMLI'}
            Recursively called cycling function.  The
            Defines the cycling used:
            cycle = 'V',    V-cycle
            cycle = 'W',    W-cycle
            cycle = 'F',    F-cycle
            cycle = 'AMLI', AMLI-cycle
        cycles_per_level : int, default 1
            Number of V-cycles on each level of an F-cycle
        r"   r/   NrP   r   rX   rZ   r   r[   rv   r\   r]   )r2   r   presmootherr0   r   r   rD   r4   r   rangezerosrJ   rw   reshapeinnerconjr   r`   r6   postsmoother)r   lvlr   rp   rb   r   r   residualcoarse_bcoarse_x_nAMLIAcpbetakjApalphas                      r   __solvezMultilevelSolver.__solve  s   * KC$$Q1---q1u9;s#%0=**#dk""Q&&&,,T[_->IIHQQQKK||S1Wh#>>>>#S1Wh%@@@S1Wh%@@@@#S1Wh%AQRRRq"233 F FALLq(Hc1EEEEF& [q)+HeX^A%67x~NNNxhnEEEu C CAAadGLLq!AqqqD'//(.*I*I!)52 2 2 #1XX 8 8%'Xa111gllnnb1QT7l%K%KHQq!!!tW\\^^R!AqqqD'\BB&CQT
!QQQ$41:!QQQ$#77 a111gBHQq!!!tW\\^^RXh5G5GHH1aaa4445E !QQQ$(G(G GGH 

8>(B(B BBHH+C.   DE D D DEEE	T[(**C%%aA.....r   r   )rP   )	Nry   rB   rP   NNNr   F)r   )r   r   r   r   r   r-   r   rO   rd   rE   rF   rk   rq   rx   ro   r   r   r   r   r   r      s@       " "H       8< < < < < < < <S0 S0 S0 S0j  (I, I, I, I,V	( 	( 	(	- 	- 	-3 3 3$( ( (': ': ': ':R IMMRy y y yvL/ L/ L/ L/ L/ L/r   r   c                     d } |           \    dv rfdn dk    rfdn dk    rfdn dk    rfd	n d
v rGt          t                     rt          t                     nt          t                     fdnB dv rdvrdd<    fdn. d n(t	                     r fdnt          d             G  fdd          } |            S )a  Return a coarse grid solver suitable for MultilevelSolver.

    Parameters
    ----------
    solver : string, callable, tuple
        The solver method is either (1) a string such as 'splu' or 'pinv' of a
        callable object which receives only parameters (A, b) and returns an
        (approximate or exact) solution to the linear system Ax = b, or (2) a
        callable object that takes parameters (A,b) and returns an (approximate
        or exact) solution to Ax = b, or (3) a tuple of the form
        (string|callable, args), where args is a dictionary of arguments to
        be passed to the function denoted by string or callable.

        The set of valid string arguments is:
            - Sparse direct methods:
                + splu : sparse LU solver
            - Sparse iterative methods:
                + the name of any method in scipy.sparse.linalg or
                  pyamg.krylov (e.g. 'cg').
                  Methods in pyamg.krylov take precedence.
                + relaxation method, such as 'gauss_seidel' or 'jacobi',
                  present in pyamg.relaxation
            - Dense methods:
                + pinv     : pseudoinverse (SVD)
                + lu       : LU factorization
                + cholesky : Cholesky factorization

    Returns
    -------
    ptr : GenericSolver
        A class for use as a standalone or coarse grids solver

    Examples
    --------
    >>> import numpy as np
    >>> from scipy.sparse import spdiags
    >>> from pyamg.gallery import poisson
    >>> from pyamg import coarse_grid_solver
    >>> A = poisson((10, 10), format='csr')
    >>> b = A * np.ones(A.shape[0])
    >>> cgs = coarse_grid_solver('lu')
    >>> x = cgs(A, b)

    c                 T    t          | t                    r| d         | d         fS | i fS )Nr   r   )r   tuple)vs    r   
unpack_argz&coarse_grid_solver.<locals>.unpack_arg  s/    a 	Q41:"ur   )r   pinv2c                     t          | d          s$t          |                                fi | _        t	          j        | j        |          S )Nr6   )r5   r   toarrayr6   r   dotr   r   rp   r   s      r   ro   z!coarse_grid_solver.<locals>.solve  sH    4%% 5aiikk44V446$&!$$$r   luc                     t          | d          s.t          j        j        |                                fi | _        t          j                            | j        |          S )NLU)r5   spr   	lu_factorr   r   lu_solver   s      r   ro   z!coarse_grid_solver.<locals>.solve  sT    4&& E)-aiikkDDVDD9%%dgq111r   choleskyc                     t          | d          s.t          j        j        |                                fi | _        t          j                            | j        |          S )NL)r5   r   r   
cho_factorr   r   	cho_solver   s      r   ro   z!coarse_grid_solver.<locals>.solve  sT    4%% E-aiikkDDVDD9&&tvq111r   spluc                    t          | d          s|                                }|                                 |j        d d         |j        dd          z
  }|dk                                    d         }t
          j                            |j        d         |j        d         d          }|d d |f         }|j	                                        |z  |z  }t          j        j
        j        |fi | _        || _        | j        | j                            t          j        | j        j	        |z                      z  S )Nr   r/   r   r   csc)format)r5   tocsceliminate_zerosindptrnonzeror   sparseeyerJ   r7   r   r   r   LU_Mapro   r   r   )r   r   rp   Acscdiffptrnonzero_colsMapr   s          r   ro   z!coarse_grid_solver.<locals>.solve  s   4&& " wwyy$$&&&+crc*T[_< '15577:immDJqM4:a=mOO!!!\/*u{{}}t+c1)*/????!;rx8I/J/J!K!KKKr   )bicgbicgstabr}   cgsgmresqmrminresc                 Z    dvrt          |j                  d<    ||fi d         S )Nrt   r   )r
   rw   )r   r   rp   fnr   s      r   ro   z!coarse_grid_solver.<locals>.solve  s@    F"" ' 0 0u2a%%f%%a((r   )gauss_seideljacobiblock_gauss_seidelschwarzblock_jacobi
richardsonsor	chebyshev	jacobi_negauss_seidel_negauss_seidel_nr
iterations
   c                     t                                           }||_        t          t          dt                    z             } ||fi }t          j        |          } ||||           |S )Nsetup_)r   r   r   r   r   r^   r   r   )	r   r   rp   r   r   relaxr   r   solvers	          r   ro   z!coarse_grid_solver.<locals>.solve  sq    "((**CCEHs6{{$:;;BBs%%f%%Ea  AE!QNNNHr   Nc                     d|z  S )Nr   r   )r   __rp   s      r   ro   z!coarse_grid_solver.<locals>.solve  s    q5Lr   c                      ||fi S r<   r   )r   r   rp   r   r   s      r   ro   z!coarse_grid_solver.<locals>.solve  s    6!Q))&)))r   zunknown solver: c                   B    e Zd ZdZ fdZfdZefd            ZdS ))coarse_grid_solver.<locals>.GenericSolverzGeneric solver class.c                    t          j        |          }|j        dk    rt          j        |j                  }n | ||          }t          |t           j                  rt          j        |          }nRt          |t           j                  r)t          j        |          }t          j        |          }nt          d          |
                    |j                  S )Nr   zunrecognized type)r   
asanyarrayr>   r   rJ   r   ndarrayasarraymatrixr   r   )r   r   rp   r   ro   s       r   __call__z2coarse_grid_solver.<locals>.GenericSolver.__call__  s    a  AuzzHQW%%E$1%%!RZ(( 6JqMMAry)) 6JqMMJqMM !455599QW%%%r   c                 .    dt                    z   dz   S )Nzcoarse_grid_solver(r]   repr)r   r   s    r   rO   z2coarse_grid_solver.<locals>.GenericSolver.__repr__  s    (4<<7#==r   c                 "    t                    S )zReturn the coarse solver name.r   )clsr   s    r   rG   z.coarse_grid_solver.<locals>.GenericSolver.name  s     <<r   N)r   r   r   r   r   rO   classmethodrG   )ro   r   s   r   GenericSolverr     sr        ##	& 	& 	& 	& 	&*	> 	> 	> 	> 	> 
	  	  	  	  
	  	  	 r   r  )r5   r   r   r   callabler   )r   r   r  r   r   ro   s   `  @@@r   r3   r3   n  s=   \  
  Z''NFF"""	% 	% 	% 	% 	% 	%
 
4	2 	2 	2 	2 	2 	2
 
:			2 	2 	2 	2 	2 	2
 
6			L 	L 	L 	L 	L 	L  
N	N	N66"" 	&((BBf%%B	) 	) 	) 	) 	) 	) 	) 
 G 
G 
G v%%#%F< 		 		 		 		 		 		 		 
	 	 	 	 
&		 6	* 	* 	* 	* 	* 	* 	* 4F44555                     @ =??r   c                   "     e Zd ZdZ fdZ xZS )multilevel_solverzlDeprecated level class.

    .. deprecated:: 4.2.3
              Use :class:`MultilevelSolver` instead.
    c                 h     t                      j        |i | t          dt          d           dS )r!   z8multilevel_solver is deprecated.  use MultilevelSolver()r"   r#   Nr&   )r   argsr   r)   s      r   r   zmultilevel_solver.__init__  sH    $)&)))G(Q	8 	8 	8 	8 	8 	8r   r*   r,   s   @r   r  r    sB         8 8 8 8 8 8 8 8 8r   r  )r   warningsr   scipyr   scipy.linalgr   scipy.sparse.linalgr   r   r   r   numpyr    r   
util.utilsr	   util.paramsr
   
relaxationr   utilr   r   r3   r  r   r   r   <module>r     sG                     ! ! ! ! ! ! ! ! ! . . . . . .                             ! ! ! ! ! !      Z	/ Z	/ Z	/ Z	/ Z	/ Z	/ Z	/ Z	/zb b bJ8 8 8 8 8( 8 8 8 8 8r   