
    _-Phӂ                     $   d Z ddlmZmZ ddlZddlmZ ddlm	Z	 ddl
mZmZmZ ddlmZ dd	lmZmZmZmZ d
dlmZ d
dlmZ dZd
Zg dZg dZd Zd Zd Zd Z d Z!d5dZ"eefdZ#eddfdZ$eddddefdZ%eefdZ&eddddfdZ'eeddfdZ(edfdZ)deefd Z*d!d"d#efd$Z+eddfd%Z,eedfd&Z-eedfd'Z.eeedd(fd)Z/eeedd(fd*Z0eeedddd(fd+Z1eeedddd(fd,Z2d-eddddfd.Z3d-edddfd/Z4d-edddfd0Z5d-edddfd1Z6d2 Z7d3 Z8d4 Z9dS )6a  Method to create pre and post-smoothers on the levels of a MultilevelSolver.

The setup_smoother_name functions are helper functions for
parsing user input and assigning each level the appropriate smoother for
the functions in 'change_smoothers'.

The standard interface is

Parameters
----------
lvl : multilevel level
    the level in the hierarchy for which to assign a smoother
iterations : int
    how many smoother iterations
optional_params : dict
    optional params specific for each method such as omega or sweep

Returns
-------
Function pointer for the appropriate relaxation method for level=lvl

Examples
--------
See change_smoothers above
    )partialupdate_wrapperN)sparse)LinearOperator   )
scale_rowsget_block_diagget_diagonal)approximate_spectral_radius)gmrescgnecgnrcg   )
relaxation)!chebyshev_polynomial_coefficientsforward)jacobi
richardsonblock_jacobi	jacobi_ne	chebyshevN)r   r   r   r   c                 T    t          | t                    r| d         | d         fS | i fS )Nr   r   )
isinstancetuple)vs    Z/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/pyamg/relaxation/smoothing.py_unpack_argr   3   s/    !U tQqTzb5L    c                    	 | j         }n"# t          $ r}t          d          |d}~ww xY w|j        t          k    rt	          d          t          j        t          j        |                    d                             t                    }t          j        |          d                             t                    }||fS )zCheck and extract splitting.z&CF splitting is required in hierarchy.Nz'CF splitting is required to be boolean.r   dtype)
	splittingAttributeErrorr"   bool
ValueErrornpwherelogical_notastypeint)lvlr#   excFptsCptss        r   _extract_splittingr0   9   s    PM		 P P PEFFCOP $BCCC8BN9--..q188s8CCD8Iq!((s(33D:s   
 
)$)c           	      f   d| _         t          |t          t          f          s||g}n$t          |t                    st          d          t          |t          t          f          s||g}n$t          |t                    st          d          d}d}i }i }t          t          |          t          |          t          | j        dd                             }t          d|          D ]}t          ||                   \  }}t          |          }	 |	| j        |         fi || j        |         _        t          ||                   \  }}t          |          }
 |
| j        |         fi || j        |         _        d|v r	|d         }nt          }d|v r	|d         }nt          }||k    rd| _         ||fd	v r|                    d
t                    }|                    d
t                    }|                    dt                    }|                    dt                    }||k    r||k    sd| _         V||k    r	d| _         e|t           v s	|t           v r	d| _         |t"          vra|                    d          r	d| _         |                    dt&                    }|                    dt&                    }||fdvrd| _         t          |          t          |          k     rt          t          |          t          | j        dd                             }t          ||          D ]} |	| j        |         fi || j        |         _        t          ||                   \  }}t          |          }
 |
| j        |         fi || j        |         _        d|v r	|d         }nt          }d|v r	|d         }nt          }||k    rd| _         ||fd	v r|                    d
t                    }|                    d
t                    }|                    dt                    }|                    dt                    }||k    r||k    sd| _         /||k    r	d| _         >|t           v s	|t           v r	d| _         Y|t"          vra|                    d          r	d| _         |                    dt&                    }|                    dt&                    }||fdvrd| _         Őn0t          |          t          |          k    rt          t          |          t          | j        dd                             }t          ||          D ]}t          ||                   \  }}t          |          }	 |	| j        |         fi || j        |         _         |
| j        |         fi || j        |         _        d|v r	|d         }nt          }d|v r	|d         }nt          }||k    rd| _         ||fd	v r|                    d
t                    }|                    d
t                    }|                    dt                    }|                    dt                    }||k    r||k    sd| _         /||k    r	d| _         >|t           v s	|t           v r	d| _         Y|t"          vra|                    d          r	d| _         |                    dt&                    }|                    dt&                    }||fdvrd| _         n|}t          |t          | j        dd                             D ]J} |	| j        |         fi || j        |         _         |
| j        |         fi || j        |         _        KdS )a  Initialize pre and post smoothers.

    Initialize pre- and post- smoothers throughout a MultilevelSolver, with
    the option of having different smoothers at different levels

    For each level of the MultilevelSolver 'ml' (except the coarsest level),
    initialize the .presmoother() and .postsmoother() methods used in the
    multigrid cycle.

    Parameters
    ----------
    ml : pyamg multilevel hierarchy
        Data structure that stores the multigrid hierarchy.
    presmoother : None, string, tuple, list
        presmoother can be (1) the name of a supported smoother, e.g.
        "gauss_seidel", (2) a tuple of the form ('method','opts') where
        'method' is the name of a supported smoother and 'opts' a dict of
        keyword arguments to the smoother, or (3) a list of instances of
        options 1 or 2.  See the Examples section for illustrations of the
        format.

        If presmoother is a list, presmoother[i] determines the smoothing
        strategy for level i.  Else, presmoother defines the same strategy
        for all levels.

        If len(presmoother) < len(ml.levels), then
        presmoother[-1] is used for all remaining levels

        If len(presmoother) > len(ml.levels), then
        the remaining smoothing strategies are ignored

    postsmoother : string, tuple, list
        Defines postsmoother in identical fashion to presmoother

    Returns
    -------
    ml changed in place
    ml.levels[i].presmoother   <===  presmoother[i]
    ml.levels[i].postsmoother  <===  postsmoother[i]
    ml.symmetric_smoothing is marked True/False depending on whether
        the smoothing scheme is symmetric.

    Notes
    -----
    - Parameter 'omega' of the Jacobi, Richardson, and jacobi_ne
      methods is scaled by the spectral radius of the matrix on
      each level.  Therefore 'omega' should be in the interval (0,2).
    - Parameter 'withrho' (default: True) controls whether the omega is
      rescaled by the spectral radius in jacobi, block_jacobi, and jacobi_ne
    - By initializing the smoothers after the hierarchy has been setup, allows
      for "algebraically" directed relaxation, such as strength_based_schwarz,
      which uses only the strong connections of a degree-of-freedom to define
      overlapping regions
    - Available smoother methods::

        gauss_seidel
        block_gauss_seidel
        jacobi
        block_jacobi
        cf_jacobi
        fc_jacobi
        cf_block_jacobi
        fc_block_jacobi
        richardson
        sor
        chebyshev
        gauss_seidel_nr
        gauss_seidel_ne
        jacobi_ne
        cg
        gmres
        cgne
        cgnr
        schwarz
        strength_based_schwarz
        None

    Examples
    --------
    >>> from pyamg.gallery import poisson
    >>> from pyamg.aggregation import smoothed_aggregation_solver
    >>> from pyamg.relaxation.smoothing import change_smoothers
    >>> from pyamg.util.linalg import norm
    >>> import numpy as np
    >>> A = poisson((10,10), format='csr')
    >>> b = np.random.rand(A.shape[0],)
    >>> ml = smoothed_aggregation_solver(A, max_coarse=10)
    >>> # Set all levels to use gauss_seidel's defaults
    >>> smoothers = 'gauss_seidel'
    >>> change_smoothers(ml, presmoother=smoothers, postsmoother=smoothers)
    >>> residuals=[]
    >>> x = ml.solve(b, tol=1e-8, residuals=residuals)
    >>> # Set all levels to use three iterations of gauss_seidel's defaults
    >>> smoothers = ('gauss_seidel', {'iterations' : 3})
    >>> change_smoothers(ml, presmoother=smoothers, postsmoother=None)
    >>> residuals=[]
    >>> x = ml.solve(b, tol=1e-8, residuals=residuals)
    >>> # Set level 0 to use gauss_seidel's defaults, and all
    >>> # subsequent levels to use 5 iterations of cgnr
    >>> smoothers = ['gauss_seidel', ('cgnr', {'maxiter' : 5})]
    >>> change_smoothers(ml, presmoother=smoothers, postsmoother=smoothers)
    >>> residuals=[]
    >>> x = ml.solve(b, tol=1e-8, residuals=residuals)

    TNzXUnrecognized presmoother -- use a string:
 "method" or ("method", opts) or list thereof.zYUnrecognized postsmoother -- use a string:
 "method" or ("method", opts) or list thereof.r   
iterationsF))	cf_jacobi	fc_jacobi)r5   r4   )cf_block_jacobifc_block_jacobi)r7   r6   f_iterationsc_iterations)cf_fc_sweep))r   backward)r=   r   )	symmetricr>   )symmetric_smoothingr   strr   listr&   minlenlevelsranger   _setup_callpresmootherpostsmootherDEFAULT_NITERgetKRYLOV_RELAXATIONSYMMETRIC_RELAXATION
startswithDEFAULT_SWEEP)mlrG   rH   fn1fn2kwargs1kwargs2min_lenisetup_presmoothersetup_postsmootherit1it2fit1fit2cit1cit2sweep1sweep2mid_lens                       r   change_smoothersra   J   se   T "B +U|,, J1D"mT** J I J J 	J ,e-- J,2F$~d++ J I J J 	J
 C
CGG#k""C$5$5s29SbS>7J7JKKG1g 53 53";q>22W',,#4#4RYq\#M#MW#M#M	!  #<?33W(--$6$6ry|$O$Ow$O$O	!! 7"",'CCC7"",'CCC#::%*B""3Z D D D
 ;;~}==D;;~}==D;;~}==D;;~}==DDLLTT\\).&CZZ%*B""%%%0A)A)A%*B"",,,~~n-- 3).&& Wm<< Wm<<F# ,H H H .3B*
;#l++++c,''RYss^)<)<==w(( 0	7 0	7A'8'81'Q'Q'Q'QBIaL$ '|A77LC!,S!1!1(:(:29Q<(S(S7(S(SBIaL% w&&l+#w&&l+ $czz).&&s  H H H {{>=AA{{>=AA{{>=AA{{>=AA-2B*).&&)))S4E-E-E).&&000>>.11 7-2B**$[[-@@F$[[-@@F' 0L L L 27.a0	7d 
[		C--	-	-c+&&BIcrcN(;(;<<w(( 1	7 1	7A&{1~66LC +C 0 0'8'81'Q'Q'Q'QBIaL$ );(:29Q<(S(S7(S(SBIaL% w&&l+#w&&l+#czz).&&s  H H H
 {{>=AA{{>=AA{{>=AA{{>=AA-2B*).&&)))S4E-E-E).&&000>>.11 7-2B**$[[-@@F$[[-@@F' 0L L L 27.c1	7f  7C	#2#//00 P P#4#4RYq\#M#MW#M#M	! $6$6ry|$O$Ow$O$O	!!!P Pr   c                     t          | d          s7t          | d          }t          | |d          }t          |          | _        | j        S )a  Return the (approx.) spectral radius of D^-1 * A.

    Parameters
    ----------
    A : sparse-matrix

    Returns
    -------
    approximate spectral radius of diag(A)^{-1} A

    Examples
    --------
    >>> from pyamg.gallery import poisson
    >>> from pyamg.relaxation.smoothing import rho_D_inv_A
    >>> from scipy.sparse import csr_matrix
    >>> import numpy as np
    >>> A = csr_matrix(np.array([[1.0,0,0],[0,2.0,0],[0,0,3.0]]))
    >>> print(f'{rho_D_inv_A(A):2.2}')
    1.0

    	rho_D_invT)inv)copy)hasattrr
   r   r   rc   )AD_invD_inv_As      r   rho_D_inv_Arj   s  sS    , 1k"" ;QD)))QD1111'::;r   c                 >    t           d          sj        d         }j        d         j        d         k    rt          d          j        d         t           j        d         |z            k    rt          d          t	          j        t          j        j        d                   t          j        j        d         dz             f j                   fd}t           j        | j	        	          }t          |           _         j        S )
aT  Return the (approx.) spectral radius of block D^-1 * A.

    Parameters
    ----------
    A : sparse-matrix
        size NxN
    Dinv : array
        Inverse of diagonal blocks of A
        size (N/blocksize, blocksize, blocksize)

    Returns
    -------
    approximate spectral radius of (Dinv A)

    Examples
    --------
    >>> from pyamg.gallery import poisson
    >>> from pyamg.relaxation.smoothing import rho_block_D_inv_A
    >>> from pyamg.util.utils import get_block_diag
    >>> A = poisson((10,10), format='csr')
    >>> Dinv = get_block_diag(A, blocksize=4, inv_flag=True)

    rho_block_D_invr   r   zDinv has incorrect dimensionsr   z'Dinv and A have incompatible dimensions)shapec                     | z  z  S N )xrg   Dinvs    r   matvecz!rho_block_D_inv_A.<locals>.matvec  s    1:r   r!   )rf   rm   r&   r+   r   
bsr_matrixr'   aranger   r"   r   rl   )rg   rr   	blocksizers   ri   s   ``   r   rho_block_D_inv_Arw     s   0 1'(( AJqM	:a=DJqM))<===:a=C
9 45555FGGG $"$)DJqM":":"$)DJqM!O"<"<"> ()w0 0 0	 	 	 	 	 	 &@@@7@@r   c                    ||z   }t          | |          }|dk    r.|t          |d                   t          |d                   z   z  }t          | |          rn|j        |k    r|dk    rt	          | ||           nc|j        |k    r,|dk    r&t	          | ||                    |                     n, t          |d|z                         }t	          | ||           t          | |          S )a  Set a matrix to a specific format.

    This routine looks for the matrix "name" in the specified format as a
    member of the level instance, lvl.  For example, if name='A', format='bsr'
    and blocksize=(4,4), and if lvl.Absr44 exists with the correct blocksize,
    then lvl.Absr is returned.  If the matrix doesn't already exist, lvl.name
    is converted to the desired format, and made a member of lvl.

    Only create such persistent copies of a matrix for routines such as
    presmoothing and postsmoothing, where the matrix conversion is done every
    cycle.

    Calling this function can _dramatically_ increase your memory costs.
    Be careful with it's usage.

    bsrr   r   )rv   to)getattrr@   rf   formatsetattrtobsr)r,   namer|   rv   desired_matrixMnewMs          r   matrix_asformatr     s   " F]NTA#il++C	!,=,===sN## +	
V		%^Q''''	
V		% 	^QWWyW%A%ABBBB )wq$-((**^T***3'''r   c                 r    t          t          j        ||          }t          |t          j                   |S )zSet up Gauss-Seidel.r3   r<   )r   r   gauss_seidelr   )r,   r3   r<   smoothers       r   setup_gauss_seidelr     s1    z.:USSSH8Z4555Or   g      ?Tc                     |r|t          | j                  z  }t          t          j        ||          }t          |t          j                   |S )zSet up weighted-Jacobi.r3   omega)rj   rg   r   r   r   r   r,   r3   r   withrhor   s        r   setup_jacobir     sM     )k#%(((z(ZuMMMH8Z.///Or   c                      t           dd            j                                         t          j         j                  \   fd}t          |t          j                   |S )zSet up Schwarz.rg   csrc                 L    t          j        j        ||		  	         d S )N)r3   	subdomainsubdomain_ptrinv_subblockinv_subblock_ptrr<   )r   schwarzAcsr)
rg   rq   br   r   r3   r,   r   r   r<   s
      r   r   zsetup_schwarz.<locals>.smoother  sE    38Qj%.)6(4,<E		K 	K 	K 	K 	K 	Kr   )r   r   sort_indicesr   schwarz_parametersr   r   )r,   r3   r   r   r   r   r<   r   s   ``````` r   setup_schwarzr     s     Ce$$$H%ch	=&24D	F 	F =I}l,<K K K K K K K K K K K 8Z/000Or   c                 4    t           d          s j                                        }n j                                        }|                                 |j                                        |j                                         fd}|S )zSet up strength-based Schwarz.Cc                 J    t                    } || ||           d S )N)r3   r   r   r<   )r   )	rg   rq   r   r   r3   r,   r   r   r<   s	       r   strength_based_schwarzz<setup_strength_based_schwarz.<locals>.strength_based_schwarz  s?     y/<EK K KAqr   )rf   rg   tocsrr   r   indptrre   indices)r,   r3   r<   r   r   r   r   s   ```  @@r   setup_strength_based_schwarzr     s    
 3 EKKMMEKKMMNNHMMOOM	  I         "!r   c                    |J|Ht          j        | j                  rd}n;t          j        | j                  r| j        j        d         }n||j        d         }|dk    r/t          | |||          }t          |t          j	                   |S |t          | j        |d          }|r|t          | j        |          z  }t          t          j	        ||||          }t          |t          j	                   |S )zSet up block Jacobi.Nr   r   r3   r   r   Trv   inv_flag)r3   r   rr   rv   )r   isspmatrix_csrrg   isspmatrix_bsrrv   rm   r   r   r   r   r	   rw   r   )r,   r3   r   rr   rv   r   r   s          r   setup_block_jacobir   &  s    T\ '' 	+II"35)) 	+*I		JqM	A~~
%QXYYYx!8999 |cey4HHH 5't444z.:U I7 7 7H8Z4555Or   c                    |J|Ht          j        | j                  rd}n;t          j        | j                  r| j        j        d         }n||j        d         }|dk    r.t          | ||          }t          |t          j	                   |S |t          | j        |d          }t          t          j	        ||||          }t          |t          j	                   |S )zSet up block Gauss-Seidel.Nr   r   r   Tr   )r3   rr   rv   r<   )r   r   rg   r   rv   rm   r   r   r   block_gauss_seidelr	   r   )r,   r3   r<   rr   rv   r   s         r   setup_block_gauss_seidelr   D  s    
 T\ '' 	+II"35)) 	+*I		JqM	A~~%cjNNNx!>??? |cey4HHHz4 IUD D DH8Z:;;;Or   c                 D    t          | j                  z  fd}|S )zSet up Richardson.c                 <    t          j        | ||g           d S N)coefficientsr3   r   
polynomial)rg   rq   r   r3   r   s      r   r   z$setup_richardson.<locals>.richardsone  s'    aAUG
SSSSSSr   )r   rg   )r,   r3   r   r   s    `` r   setup_richardsonr   a  sC    -ce444ET T T T T Tr   g      ?c                 t    t          t          j        |||          }t          |t          j                   |S )zSet up SOR.)r3   r   r<   )r   r   sorr   )r,   r   r3   r<   r   s        r   	setup_sorr   j  s2    z~*EQVWWWH8Z^,,,Or   g?g?   c                    	 t          | j                  }||z  }||z  }t          |||          dd          		fd}|S )zSet up Chebyshev.Nr2   c                 :    t          j        | ||           d S r   r   )rg   rq   r   r   r3   s      r   r   z"setup_chebyshev.<locals>.chebyshevz  s%    aALZXXXXXXr   )r   rg   r   )
r,   lower_boundupper_bounddegreer3   rhoar   r   r   s
       `    @r   setup_chebyshevr   q  sp     &ce
,
,CkAkA5aFCCCRCHHLY Y Y Y Y Yr   c                      t           dd           |rt           j                  dz  z   fd}t          |t          j                   |S )zSet up Jacobi NE.rg   r   r   c                 D    t          j        j        ||           d S )Nr   )r   r   r   )rg   rq   r   r3   r,   r   s      r   r   z!setup_jacobi_ne.<locals>.smoother  s4    SXq!
#(	* 	* 	* 	* 	* 	*r   )r   rj   r   r   r   r   r   s   ```  r   setup_jacobi_ner     su    Ce$$$ /k#(++Q..* * * * * * * 8Z1222Or   c                 t     t           dd            fd}t          |t          j                   |S )zSet up Gauss-Seidel NE.rg   r   c                 F    t          j        j        ||           d S N)r3   r<   r   )r   gauss_seidel_ner   rg   rq   r   r3   r,   r   r<   s      r   r   z'setup_gauss_seidel_ne.<locals>.smoother  6    "38Qj).e	= 	= 	= 	= 	= 	=r   )r   r   r   r   r,   r3   r<   r   r   s   ```` r   setup_gauss_seidel_ner     \     Ce$$$= = = = = = = = 8Z7888Or   c                 t     t           dd            fd}t          |t          j                   |S )zSet up Gauss-Seidel NR.rg   cscc                 F    t          j        j        ||           d S r   )r   gauss_seidel_nrAcscr   s      r   r   z'setup_gauss_seidel_nr.<locals>.smoother  r   r   )r   r   r   r   r   s   ```` r   setup_gauss_seidel_nrr     r   r   Fc           	          |r|t          | j                  z  }t          |           \  }}t          t          j        ||||||          }t          |t          j                   |S )zSet up coarse-fine Jacobi.r/   r.   r8   r9   r3   r   )rj   rg   r0   r   r   r4   r   	r,   r8   r9   r3   r   r   r.   r/   r   s	            r   setup_cf_jacobir     r      )k#%(((#C((JD$z+$T$0|",E; ; ;H 8Z1222Or   c           	          |r|t          | j                  z  }t          |           \  }}t          t          j        ||||||          }t          |t          j                   |S )zSet up fine-coarse Jacobi.r   )rj   rg   r0   r   r   r5   r   r   s	            r   setup_fc_jacobir     r   r   c                    |J|Ht          j        | j                  rd}nRt          j        | j                  r| j        j        d         }n&|$t          j        |          r|j        d         }nd}| j        j        d         |z  dk    rt          d          t          | j                  |z  | j        j        d         k    rt          d          |dk    r/t          | |||          }t          |t          j                   |S t          |           \  }	}
|t          | j        |d          }|r|t          | j        |          z  }t!          t          j        |
|	||||||		  	        }t          |t          j                   |S 
z Set up coarse-fine block Jacobi.Nr   r   z)Blocksize does not divide size of matrix.z;Blocksize not compatible with CF-splitting and matrix size.r   Tr   )r/   r.   r8   r9   r3   r   rr   rv   )r   r   rg   r   rv   rm   r&   rC   r#   r   r   r   r6   r0   r	   rw   r   r,   r8   r9   r3   r   rr   rv   r   r   r.   r/   s              r   setup_cf_block_jacobir        
 T\ '' 	+II"35)) 	+*I		 && 	q)III 	A"q((DEEE
3=)#su{1~55VWWWA~~"3:UT[\\\x!;<<<#C((JD$ |cey4HHH 5't444z14$0",EPY[ [ [H 8Z7888Or   c                    |J|Ht          j        | j                  rd}nRt          j        | j                  r| j        j        d         }n&|$t          j        |          r|j        d         }nd}| j        j        d         |z  dk    rt          d          t          | j                  |z  | j        j        d         k    rt          d          |dk    r/t          | |||          }t          |t          j                   |S t          |           \  }	}
|t          | j        |d          }|r|t          | j        |          z  }t!          t          j        |
|	||||||		  	        }t          |t          j                   |S r   )r   r   rg   r   rv   rm   r&   rC   r#   r   r   r   r7   r0   r	   rw   r   r   s              r   setup_fc_block_jacobir     r   r   g-q=c                 P    fd}t          |t                     |S )zSet up GMRES smoothing.c                 ~    t          | ||	  	        d                             |j                  |d d <   d S )N)x0tolmaxiterrestartr   callback	residualsr   )r   reshaperm   )	rg   rq   r   r   r   r   r   r   r   s	      r   r   zsetup_gmres.<locals>.smoother  sQ    QaS'7a&)= = ==>@@G@P@P 	
!!!r   )r   r   )r,   r   r   r   r   r   r   r   s    `````` r   setup_gmresr     s[    Q Q Q Q Q Q Q Q Q Q 8U###Or   c                 L    fd}t          |t                     |S )zSet up CG smoothing.c           
      |    t          | ||          d                             |j                  |d d <   d S N)r   r   r   r   r   r   r   )r   r   rm   rg   rq   r   r   r   r   r   r   s      r   r   zsetup_cg.<locals>.smoother$  sN    !Q1#w!#y: : ::;==DWQW=M=M 	
!!!r   )r   r   r,   r   r   r   r   r   r   s    ````` r   setup_cgr   "  sT    N N N N N N N N N 8R   Or   c                 L    fd}t          |t                     |S )zSet up CGNE smoothing.c           
      |    t          | ||          d                             |j                  |d d <   d S r   )r   r   rm   r   s      r   r   zsetup_cgne.<locals>.smoother.  N    AqQCA%< < <<=??Fwqw?O?O 	
!!!r   )r   r   r   s    ````` r   
setup_cgner   +  T    P P P P P P P P P 8T"""Or   c                 L    fd}t          |t                     |S )zSet up CGNR smoothing.c           
      |    t          | ||          d                             |j                  |d d <   d S r   )r   r   rm   r   s      r   r   zsetup_cgnr.<locals>.smoother8  r   r   )r   r   r   s    ````` r   
setup_cgnrr   5  r   r   c                     d }|S )zSet up default, empty smoother.c                     d S ro   rp   )rg   rq   r   s      r   nonezsetup_none.<locals>.noneA  s    r   rp   )r,   r   s     r   
setup_noner   ?  s      Kr   c                    i dt           dt          dt          dt          dt          dt
          dt          dt          d	t          d
t          dt          dt          dt          dt          dt          dt          dt           t"          t$          t&          t(          d}| d} t+          | t,                    st/          d|            | |vrt/          d|  d          ||          S )zqRegister setup functions.

    This is a helper function to call the setup methods and avoids use of eval().
    r   r   r   r   r   r   r   r   r   r   r   r   r4   r5   r6   r7   r   )r   r   r   r   Nr   z,Input function must be a string or None: fn=z	Function z does not have a setup)r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r@   r&   )fnsetup_registers     r   rF   rF   F  s]   
"4, 	- 	!">	
 	"4 	": 	"2 	) 	/ 	/ 	"7 	"7 	/ 	/ 	"7  	"7!" 	+#$ #+",",",+  N0 
zb# NLLLMMM	?R???@@@"r   c                     	 | j         j        }| j        j        }n"# t          $ r}t          d          |d}~ww xY wt	          |          } ||           | _         t	          |          } ||           | _        dS )a  Rebuild the pre/post smoother on a level.

    Parameters
    ----------
    lvl : Level object

    Notes
    -----
    This rebuilds a smoother on level lvl using the existing pre
    and post smoothers.  If different methods are needed, see
    `change_smoothers`.
    z,The pre/post smoothers need to be functions.N)rG   __name__rH   r$   rF   )r,   rP   rQ   r-   rV   rW   s         r   rebuild_smootherr  o  s    Vo&' V V VKLLRUUV $C(('',,CO %S))))#..Cs    
:5:ro   ):__doc__	functoolsr   r   numpyr'   scipyr   scipy.sparse.linalgr   
util.utilsr   r	   r
   util.linalgr   krylovr   r   r   r    r   r   r   rN   rI   rL   rK   r   r0   ra   rj   rw   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rF   r  rp   r   r   <module>r     s+   4 . - - - - - - -           . . . . . . A A A A A A A A A A 5 5 5 5 5 5 * * * * * * * * * * * *       8 8 8 8 8 8 8 8 8  433     "fP fP fPR	  <- - -b&( &( &( &(T (5M     "/c4     #04 $4$%   ( 2?'4" " " "* (5Cd!%t   < .;#0"&$   : &3#     m     &.3q,    %2d 
 
 
 
 +8} #	 	 	 	 +8} #	 	 	 	 '4-,C    '4-,C    -:%2#DTX"'( ( ( (V -:%2#DTX"'( ( ( (V ttVZ    ]dTUY     }t    }t     & & &R/ / / / /r   