code: def profile_solver(ml, accel=None, **kwargs):
      
      A = ml.levels[0].A
      b = A * sp.rand(A.shape[0], 1)
      residuals = []
  
      if accel is None:
          ml.solve(b, residuals=residuals, **kwargs)
      else:
          def callback(x):
              residuals.append(norm(np.ravel(b) - np.ravel(A*x)))
          M = ml.aspreconditioner(cycle=kwargs.get('cycle', 'V'))
          accel(A, b, M=M, callback=callback, **kwargs)
  
      return np.asarray(residuals)
docs: Profile a particular multilevel object.
  
      Parameters
      ----------
      ml : multilevel
          Fully constructed multilevel object
      accel : function pointer
          Pointer to a valid Krylov solver (e.g. gmres, cg)
  
      Returns
      -------
      residuals : array
          Array of residuals for each iteration
  
      See Also
      --------
      multilevel.psolve, multilevel.solve
  
      Examples
      --------
      >>> import numpy as np
      >>> from scipy.sparse import spdiags, csr_matrix
      >>> from scipy.sparse.linalg import cg
      >>> from pyamg.classical import ruge_stuben_solver
      >>> from pyamg.util.utils import profile_solver
      >>> n=100
      >>> e = np.ones((n,1)).ravel()
      >>> data = [ -1*e, 2*e, -1*e ]
      >>> A = csr_matrix(spdiags(data,[-1,0,1],n,n))
      >>> b = A*np.ones(A.shape[0])
      >>> ml = ruge_stuben_solver(A, max_coarse=10)
      >>> res = profile_solver(ml,accel=cg)