Esempio n. 1
0
def solver_pcg_amg(A):
    """ 
    Return a function for solving a sparse linear system using PCG with AMG.
    
    Parameters
    ----------
    A : (N, N) array_like
        Input.
        
    Returns
    -------
    solve : callable
        To solve the linear system of equations given in `A`, the `solve`
        callable should be passed an ndarray of shape (N,).
        
    """

    from scipy.sparse.linalg import cg
    from pyamg import rootnode_solver

    M = rootnode_solver(A.T).aspreconditioner(cycle='V')

    def solver(b, x0=None):
        x, info = cg(A.T, b, x0=x0, M=M)
        if info != 0:
            raise ValueError(f'CG failed: info={info}')
        return x

    return solver,
Esempio n. 2
0
    def __init__(self,
                 linear_op: LinearOperator,
                 heuristic: str = 'ruge_stuben',
                 cycle: str = 'F',
                 n_cycles: int = 1,
                 **kwargs):
        """
        Abstract representation for Algebraic Multi-grid (AMG) class of preconditioners. Available heuristics are the
        one from the PyAMG Python library.

        :param linear_op: Linear operator to build the algebraic multi-grid preconditioner on.
        :param heuristic: Name of the algebraic multi-grid heuristic used for multi-level hierarchy construction.
        :param cycle: Type of cycle of the multigrid method, either "V", "W", "F" or "AMLI".
        :param n_cycles: Number of cycles done per application of the multi-grid method as a preconditioner.
        """
        # Sanitize the heuristic argument
        if heuristic not in ['ruge_stuben', 'smoothed_aggregated', 'rootnode']:
            raise PreconditionerError(
                'AMG heuristic {} unknown.'.format(heuristic))

        matrix_repr = linear_op.mat

        # Setup multi-grid hierarchical structure with corresponding heuristic
        if heuristic == 'ruge_stuben':
            self.amg = pyamg.ruge_stuben_solver(matrix_repr.tocsr(), **kwargs)

        elif heuristic == 'smoothed_aggregated':
            self.amg = pyamg.smoothed_aggregation_solver(
                matrix_repr.tocsr(), **kwargs)

        elif heuristic == 'rootnode':
            self.amg = pyamg.rootnode_solver(matrix_repr.tocsr(), **kwargs)

        # Sanitize the number of cycles argument
        if not isinstance(n_cycles, int) or n_cycles < 1:
            raise PreconditionerError(
                'Number of cycles must be a positive integer, received {}.'.
                format(n_cycles))

        # Sanitize the cycle argument
        if cycle not in ['V', 'F', 'W', 'AMLI']:
            raise PreconditionerError(
                'AMG cycle type {} unknown.'.format(cycle))

        self.cycle = cycle
        self.n_cycles = n_cycles

        # Get hierarchy key attributes
        self.cycle_complexity = self.amg.cycle_complexity(cycle=self.cycle)
        self.operator_complexity = self.amg.operator_complexity()

        self.levels = self.amg.levels
        self.amg = self.amg.aspreconditioner(cycle=self.cycle)

        super().__init__(linear_op)
Esempio n. 3
0
    def build_pyamg(self, A):
        try:
            import pyamg
        except:
            raise ImportError(f"*** pyamg not found {self.linearsolver=} ***")
        # return pyamg.smoothed_aggregation_solver(A)
        B = np.ones((A.shape[0], 1))
        B = pyamg.solver_configuration(A, verb=False)['B']
        if self.convection:
            symmetry = 'nonsymmetric'
            # smoother = 'gauss_seidel_nr'
            smoother = 'gauss_seidel'
            smoother = 'block_gauss_seidel'
            smoother = 'strength_based_schwarz'
            smoother = 'schwarz'
            # smoother = 'own_gs'
            # smoother = 'gmres'

            # global setup_own_gs
            # def setup_own_gs(lvl, iterations=2, sweep='forward'):
            #     def smoother(A, x, b):
            #         pyamg.relaxation.gauss_seidel(A, x, b, iterations=iterations, sweep=sweep)
            #
            #     return smoother

            # smoother = 'own_gs'
            # smooth = ('energy', {'krylov': 'fgmres'})
            smooth = ('energy', {'krylov': 'bicgstab'})
            # improve_candidates =[ (smoother, {'sweep': 'symmetric', 'iterations': 4}), None]
            improve_candidates = None
        else:
            symmetry = 'hermitian'
            smooth = ('energy', {'krylov': 'cg'})
            smoother = 'gauss_seidel'
            # improve_candidates =[ ('gauss_seidel', {'sweep': 'symmetric', 'iterations': 4}), None]
            improve_candidates = None
        # strength = [('evolution', {'k': 2, 'epsilon': 10.0})]
        strength = [('symmetric', {'theta': 0.05})]
        psmoother = (smoother, {'sweep': 'symmetric', 'iterations': 1})
        # psmoother = (smoother, {'maxiter': 10})
        SA_build_args = {
            'max_levels': 10,
            'max_coarse': 25,
            'coarse_solver': 'pinv2',
            'symmetry': symmetry,
            'smooth': smooth,
            'strength': strength,
            'presmoother': psmoother,
            'presmoother': psmoother,
            'improve_candidates': improve_candidates,
            'diagonal_dominance': False
        }
        # return pyamg.smoothed_aggregation_solver(A, B, **SA_build_args)
        return pyamg.rootnode_solver(A, B, **SA_build_args)
Esempio n. 4
0
    def _linear_analysis(self, method, **kwargs):
        """Performs the linear analysis, in which the pressure and flow fields
        are computed.
        INPUT: method: This can be either 'direct' or 'iterative'
               **kwargs
               precision: The accuracy to which the ls is to be solved. If not
                          supplied, machine accuracy will be used. (This only
                          applies to the iterative solver)
        OUTPUT: The maximum, mean, and median pressure change. Moreover,
                pressure and flow are modified in-place.
        """

        G = self._G
        A = self._A.tocsr()
        if method == 'direct':
            linalg.use_solver(useUmfpack=True)
            x = linalg.spsolve(A, self._b)
        elif method == 'iterative':
            if kwargs.has_key('precision'):
                eps = kwargs['precision']
            else:
                eps = self._eps
            AA = smoothed_aggregation_solver(A, max_levels=10, max_coarse=500)
            x = abs(AA.solve(self._b, x0=None, tol=eps, accel='cg', cycle='V', maxiter=150))
            # abs required, as (small) negative pressures may arise
        elif method == 'iterative2':
         # Set linear solver
             ml = rootnode_solver(A, smooth=('energy', {'degree':2}), strength='evolution' )
             M = ml.aspreconditioner(cycle='V')
             # Solve pressure system
             #x,info = gmres(A, self._b, tol=self._eps, maxiter=50, M=M, x0=self._x)
             #x,info = gmres(A, self._b, tol=self._eps/10000000000000, maxiter=50, M=M)
             x,info = gmres(A, self._b, tol=self._eps/10000, maxiter=50, M=M)
             if info != 0:
                 print('SOLVEERROR in Solving the Matrix')

        pdiff = map(abs, [(p - xx) / p if p > 0 else 0.0
                          for p, xx in zip(G.vs['pressure'], x)])
        maxPDiff = max(pdiff)
        meanPDiff = np.mean(pdiff)
        medianPDiff = np.median(pdiff)
        log.debug(np.nonzero(np.array(pdiff) == maxPDiff)[0])

        G.vs['pressure'] = x
        G.es['flow'] = [abs(G.vs[edge.source]['pressure'] -   \
                            G.vs[edge.target]['pressure']) *  \
                        edge['conductance'] for edge in G.es]

	self._maxPDiff=maxPDiff
        self._meanPDiff=meanPDiff
        self._medianPDiff=medianPDiff

        return maxPDiff, meanPDiff, medianPDiff
def mode_solver_initialisation(mode, solver_data, a, solver_tol):
    solver_data['solver_timing'], solver_data['solver_tol'] = [], solver_tol
    solver_data['is_solver_direct'] = []
    
    id_n = sp.eye(a.shape[0], format='csr')
    solver_data['a'] = a
    solver_data['id_n'] = id_n

    if mode == 'pyamg':
        amg_hierarchy = pyamg.ruge_stuben_solver(a)
        orig_hierarchy = copy_hierarchy(amg_hierarchy)
        solver_data['amg_hierarchy'], solver_data['orig_hierarchy'] = amg_hierarchy, orig_hierarchy
    elif mode == 'pyamgE':
        B = np.ones((a.shape[0],1), dtype=a.dtype);
        amg_hierarchy = pyamg.rootnode_solver(a, max_levels = 15, max_coarse = 300, coarse_solver = 'pinv', presmoother = ('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}), postsmoother = ('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}), BH = B.copy(), 
                                              strength = ('evolution', {'epsilon': 4.0, 'k': 2, 'proj_type': 'l2'}), aggregate ='standard', smooth = ('energy', {'weighting': 'local', 'krylov': 'gmres', 'degree': 1, 'maxiter': 2}), improve_candidates = [('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 4}), None, None, None, None, None, None, None, None, None, None, None, None, None, None]) 
        orig_hierarchy = copy_hierarchy(amg_hierarchy)
        solver_data['amg_hierarchy'], solver_data['orig_hierarchy'] = amg_hierarchy, orig_hierarchy
    elif mode == 'splu':
        solver_data['lu'] = sla.splu(a.tocsc())
    return
Esempio n. 6
0
 def __init__(self, A, **kwargs):
     try:
         import pyamg
     except:
         raise ImportError(f"*** pyamg not found ***")
     self.method = 'pyamg'
     self.matvec = A
     nsmooth = kwargs.pop('nsmooth', 1)
     self.smoother = kwargs.pop('smoother', 'schwarz')
     symmetric = kwargs.pop('symmetric', False)
     self.type = kwargs.pop('pyamgtype', 'aggregation')
     self.accel = kwargs.pop('accel', None)
     if self.accel == 'none': self.accel = None
     pyamgargs = {'B': pyamg.solver_configuration(A, verb=False)['B']}
     smoother = (self.smoother, {
         'sweep': 'symmetric',
         'iterations': nsmooth
     })
     if symmetric:
         smooth = ('energy', {'krylov': 'cg'})
     else:
         smooth = ('energy', {'krylov': 'fgmres'})
         pyamgargs['symmetry'] = 'nonsymmetric'
     pyamgargs['presmoother'] = smoother
     pyamgargs['postsmoother'] = smoother
     # pyamgargs['smooth'] = smooth
     # pyamgargs['coarse_solver'] = 'splu'
     if self.type == 'aggregation':
         self.mlsolver = pyamg.smoothed_aggregation_solver(A, **pyamgargs)
     elif self.type == 'rootnode':
         self.mlsolver = pyamg.rootnode_solver(A, **pyamgargs)
     else:
         raise ValueError(f"unknown {self.type=}")
     self.solver = self.mlsolver.solve
     #        cycle : {'V','W','F','AMLI'}
     super().__init__(**kwargs)
     self.args['cycle'] = 'V'
     self.args['accel'] = self.accel
Esempio n. 7
0
    def solve(self, method):
        """Solves the linear system A x = b for the vector of unknown pressures
        x, either using a direct solver (obsolete) or an iterative GMRES solver. From the
        pressures, the flow field is computed.
        INPUT: method: This can be either 'direct' or 'iterative2'
        OUTPUT: None - G is modified in place.
                G_final.pkl & G_final.vtp: are save as output
                sampledict.pkl: is saved as output
        """
        b = self._b
        A = self._A
        G = self._G
        htt2htd = self._P.tube_to_discharge_hematocrit
        
        A = self._A.tocsr()
        if method == 'direct':
            linalg.use_solver(useUmfpack=True)
            x = linalg.spsolve(A, b)
        elif method == 'iterative2':
             ml = rootnode_solver(A, smooth=('energy', {'degree':2}), strength='evolution' )
             M = ml.aspreconditioner(cycle='V')
             # Solve pressure system
             x,info = gmres(A, self._b, tol=1000*self._eps, maxiter=200, M=M)
             if info != 0:
                 print('ERROR in Solving the Matrix')
                 print(info)

        G.vs['pressure'] = x
        G.es['flow'] = [abs(G.vs[edge.source]['pressure'] - G.vs[edge.target]['pressure']) *  \
                        edge['conductance'] for edge in G.es]

        #Default Units - mmHg for pressure
        G.vs['pressure'] = [v['pressure']/self._scalingFactor for v in G.vs]

        if self._withRBC:
	        G.es['v']=[e['htd']/e['htt']*e['flow']/(0.25*np.pi*e['diameter']**2) for e in G.es]
        else:
	        G.es['v']=[e['flow']/(0.25*np.pi*e['diameter']**2) for e in G.es]
Esempio n. 8
0
print "Test convergence for a simple 200x200 Grid, Linearized Elasticity Problem"
choice = input('\n Input Choice:\n' + \
           '1:  Run smoothed_aggregation_solver\n' + \
           '2:  Run rootnode_solver\n' )

# Create matrix and candidate vectors.  B has 3 columns, representing
# rigid body modes of the mesh. B[:,0] and B[:,1] are translations in
# the X and Y directions while B[:,2] is a rotation.
A, B = linear_elasticity((200, 200), format='bsr')

# Construct solver using AMG based on Smoothed Aggregation (SA)
if choice == 1:
    mls = smoothed_aggregation_solver(A, B=B, smooth='energy')
elif choice == 2:
    mls = rootnode_solver(A, B=B, smooth='energy')
else:
    raise ValueError("Enter a choice of 1 or 2")

# Display hierarchy information
print mls

# Create random right hand side
b = scipy.rand(A.shape[0], 1)

# Solve Ax=b
residuals = []
x = mls.solve(b, tol=1e-10, residuals=residuals)
print "Number of iterations:  %d\n" % len(residuals)

# Output convergence
Esempio n. 9
0
''' 
Example driver script for solver_diagnostics.py, which tries different
parameter combinations for smoothed_aggregation_solver(...) and
rootnode_solver(...).  The goal is to find appropriate parameter settings
for an arbitrary matrix.

Explore 4 different matrices: CSR matrix for basic isotropic diffusion
                              CSR matrix for basic rotated anisotropic diffusion
                              BSR matrix for basic 2D linearized elasticity
                              CSR matrix for a nonsymmetric recirculating flow problem  

Many more solver parameters may be specified than outlined in the below
examples.  Only the most basic are shown.

Run with 
    >>> python demo.py
and examine the on-screen output and file output.
'''
from scipy import pi
from pyamg import gallery
from pyamg.gallery import diffusion
stencil = diffusion.diffusion_stencil_2d(type='FE',
                                         epsilon=0.001,
                                         theta=2 * pi / 16.0)
A = gallery.stencil_grid(stencil, (50, 50), format='csr')

from pyamg import gallery
from solver_diagnostics import solver_diagnostics
from scipy import pi
from pyamg.gallery import diffusion
Esempio n. 10
0
"""
import numpy as np
import pyamg
from convergence_tools import print_cycle_history

n = 100

print("Test convergence for a simple 100x100 Grid, Gauge Laplacian")
choice = input('\n Input Choice:\n' + '1:  Run smoothed_aggregation_solver\n' +
               '2:  Run rootnode_solver\n')

np.random.seed(625)
A = pyamg.gallery.gauge_laplacian(n, beta=0.001)
x = np.random.rand(A.shape[0]) + 1.0j * np.random.rand(A.shape[0])
b = np.random.rand(A.shape[0]) + 1.0j * np.random.rand(A.shape[0])

choice = int(choice)

if choice == 1:
    ml = pyamg.smoothed_aggregation_solver(A, smooth='energy')
elif choice == 2:
    ml = pyamg.rootnode_solver(A, smooth='energy')
else:
    raise ValueError("Enter a choice of 1 or 2")

resvec = []
x = ml.solve(b, x0=x, maxiter=20, tol=1e-14, residuals=resvec)

for i, r in enumerate(resvec):
    print("residual at iteration {0:2}: {1:^6.2e}".format(i, r))
Esempio n. 11
0
##
# Construct solver and solve
if choice == 1:
    sa_symmetric = pyamg.smoothed_aggregation_solver(A,
                                                     B=B,
                                                     smooth=smooth,
                                                     strength=strength,
                                                     presmoother=presmoother,
                                                     postsmoother=postsmoother,
                                                     **SA_build_args)
elif choice == 2:
    sa_symmetric = pyamg.rootnode_solver(A,
                                         B=B,
                                         smooth=smooth,
                                         strength=strength,
                                         presmoother=presmoother,
                                         postsmoother=postsmoother,
                                         **SA_build_args)
else:
    raise ValueError("Enter a choice of 1 or 2")

sa_symmetric = pyamg.smoothed_aggregation_solver(A,
                                                 B=B,
                                                 smooth=smooth,
                                                 strength=strength,
                                                 presmoother=presmoother,
                                                 postsmoother=postsmoother,
                                                 **SA_build_args)
resvec = []
x = sa_symmetric.solve(b, x0=x0, residuals=resvec, **SA_solve_args)
Esempio n. 12
0
    SA_build_args={'max_levels':10, 'max_coarse':25, 'coarse_solver':'pinv2', \
                   'symmetry':'hermitian'}
    SA_solve_args={'cycle':'V', 'maxiter':15, 'tol':1e-8}
    strength=[('evolution', {'k':2, 'epsilon':4.0})]
    presmoother =('gauss_seidel', {'sweep':'symmetric', 'iterations':1})
    postsmoother=('gauss_seidel', {'sweep':'symmetric', 'iterations':1})

    ##
    # Construct solver and solve
    if choice == 1:
        sa_symmetric = smoothed_aggregation_solver(A, B=B, smooth=smooth, \
                   strength=strength, presmoother=presmoother, \
                   postsmoother=postsmoother, **SA_build_args)
    elif choice == 2:
        sa_symmetric = rootnode_solver(A, B=B, smooth=smooth, \
                   strength=strength, presmoother=presmoother, \
                   postsmoother=postsmoother, **SA_build_args)
    else:
        raise ValueError("Enter a choice of 1 or 2")


    sa_symmetric = smoothed_aggregation_solver(A, B=B, smooth=smooth, \
                   strength=strength, presmoother=presmoother, \
                   postsmoother=postsmoother, **SA_build_args)
    resvec = []
    x = sa_symmetric.solve(b, x0=x0, residuals=resvec, **SA_solve_args)
    print "\nObserve that standard SA parameters for Hermitian systems\n" + \
          "yield a nonconvergent stand-alone solver.\n"
    print_cycle_history(resvec, sa_symmetric, verbose=True, plotting=False)

    ##
Esempio n. 13
0
    def solve(self, method, **kwargs):
        """Solves the linear system A x = b for the vector of unknown pressures
        x, either using a direct solver (obsolete) or an iterative GMRES solver. From the
        pressures, the flow field is computed.
        INPUT: method: This can be either 'direct' or 'iterative2'
        OUTPUT: None - G is modified in place.
                G_final.pkl & G_final.vtp: are save as output
                sampledict.pkl: is saved as output
        """
        b = self._b
        G = self._G
        htt2htd = self._P.tube_to_discharge_hematocrit

        A = self._A.tocsr()
        if method == 'direct':
            linalg.use_solver(useUmfpack=True)
            x = linalg.spsolve(A, b)
        elif method == 'iterative2':
            ml = rootnode_solver(A,
                                 smooth=('energy', {
                                     'degree': 2
                                 }),
                                 strength='evolution')
            M = ml.aspreconditioner(cycle='V')
            # Solve pressure system
            #x,info = gmres(A, self._b, tol=self._eps, maxiter=1000, M=M)
            x, info = gmres(A, self._b, tol=10 * self._eps, M=M)
            if info != 0:
                print('ERROR in Solving the Matrix')
                print(info)

        G.vs['pressure'] = x
        self._x = x
        conductance = self._conductance
        G.es['flow'] = [abs(G.vs[edge.source]['pressure'] - G.vs[edge.target]['pressure']) *  \
                        conductance[i] for i, edge in enumerate(G.es)]

        #Default Units - mmHg for pressure
        for v in G.vs:
            v['pressure'] = v['pressure'] / vgm.units.scaling_factor_du(
                'mmHg', G['defaultUnits'])

        if self._withRBC:
            G.es['v'] = [
                e['htd'] / e['htt'] * e['flow'] /
                (0.25 * np.pi * e['diameter']**2) for e in G.es
            ]
        else:
            G.es['v'] = [
                e['flow'] / (0.25 * np.pi * e['diameter']**2) for e in G.es
            ]

        #Convert 'pBC' from default Units to mmHg
        pBCneNone = G.vs(pBC_ne=None).indices
        G.vs[pBCneNone]['pBC'] = np.array(G.vs[pBCneNone]['pBC']) * (
            1 / vgm.units.scaling_factor_du('mmHg', G['defaultUnits']))

        vgm.write_pkl(G, 'G_final.pkl')
        vgm.write_vtp(G, 'G_final.vtp', False)

        #Write Output
        sampledict = {}
        for eprop in ['flow', 'v']:
            if not eprop in sampledict.keys():
                sampledict[eprop] = []
            sampledict[eprop].append(G.es[eprop])
        for vprop in ['pressure']:
            if not vprop in sampledict.keys():
                sampledict[vprop] = []
            sampledict[vprop].append(G.vs[vprop])

            g_output.write_pkl(sampledict, 'sampledict.pkl')
Esempio n. 14
0
import numpy
import scipy
from pyamg.gallery import gauge_laplacian
from pyamg import smoothed_aggregation_solver, rootnode_solver
from convergence_tools import print_cycle_history

if __name__ == '__main__':
    n = 100

    print "Test convergence for a simple 100x100 Grid, Gauge Laplacian"
    choice = input('\n Input Choice:\n' + \
               '1:  Run smoothed_aggregation_solver\n' + \
               '2:  Run rootnode_solver\n' )

    numpy.random.seed(625)
    A = gauge_laplacian(n, beta=0.001)
    x = scipy.rand(A.shape[0]) + 1.0j * scipy.rand(A.shape[0])
    b = scipy.rand(A.shape[0]) + 1.0j * scipy.rand(A.shape[0])

    if choice == 1:
        sa = smoothed_aggregation_solver(A, smooth='energy')
    elif choice == 2:
        sa = rootnode_solver(A, smooth='energy')
    else:
        raise ValueError("Enter a choice of 1 or 2")

    resvec = []
    x = sa.solve(b, x0=x, maxiter=20, tol=1e-14, residuals=resvec)

    print_cycle_history(resvec, sa, verbose=True, plotting=True)
Esempio n. 15
0
##
# Construct solver and solve
if choice == 1:
    sa_symmetric = pyamg.smoothed_aggregation_solver(
        A,
        B=B,
        smooth=smooth,
        strength=strength,
        presmoother=presmoother,
        postsmoother=postsmoother,
        **SA_build_args)
elif choice == 2:
    sa_symmetric = pyamg.rootnode_solver(
        A,
        B=B,
        smooth=smooth,
        strength=strength,
        presmoother=presmoother,
        postsmoother=postsmoother,
        **SA_build_args)
else:
    raise ValueError("Enter a choice of 1 or 2")

sa_symmetric = pyamg.smoothed_aggregation_solver(
    A,
    B=B,
    smooth=smooth,
    strength=strength,
    presmoother=presmoother,
    postsmoother=postsmoother,
    **SA_build_args)
resvec = []
Esempio n. 16
0
    def _linear_analysis(self, method, **kwargs):
        """Performs the linear analysis, in which the pressure and flow fields
        are computed.
        INPUT: method: This can be either 'direct' or 'iterative'
               **kwargs
               precision: The accuracy to which the ls is to be solved. If not
                          supplied, machine accuracy will be used. (This only
                          applies to the iterative solver)
        OUTPUT: The maximum, mean, and median pressure change. Moreover,
                pressure and flow are modified in-place.
        """

        G = self._G
        A = self._A.tocsr()
        if method == 'direct':
            linalg.use_solver(useUmfpack=True)
            x = linalg.spsolve(A, self._b)
        elif method == 'iterative':
            if kwargs.has_key('precision'):
                eps = kwargs['precision']
            else:
                eps = self._eps
            AA = smoothed_aggregation_solver(A, max_levels=10, max_coarse=500)
            x = abs(
                AA.solve(self._b,
                         x0=None,
                         tol=eps,
                         accel='cg',
                         cycle='V',
                         maxiter=150))
            # abs required, as (small) negative pressures may arise
        elif method == 'iterative2':
            # Set linear solver
            ml = rootnode_solver(A,
                                 smooth=('energy', {
                                     'degree': 2
                                 }),
                                 strength='evolution')
            M = ml.aspreconditioner(cycle='V')
            # Solve pressure system
            #x,info = gmres(A, self._b, tol=self._eps, maxiter=50, M=M, x0=self._x)
            #x,info = gmres(A, self._b, tol=self._eps/10000000000000, maxiter=50, M=M)
            x, info = gmres(A, self._b, tol=self._eps / 10000, maxiter=50, M=M)
            if info != 0:
                print('SOLVEERROR in Solving the Matrix')

        pdiff = map(abs, [(p - xx) / p if p > 0 else 0.0
                          for p, xx in zip(G.vs['pressure'], x)])
        maxPDiff = max(pdiff)
        meanPDiff = np.mean(pdiff)
        medianPDiff = np.median(pdiff)
        log.debug(np.nonzero(np.array(pdiff) == maxPDiff)[0])

        G.vs['pressure'] = x
        G.es['flow'] = [abs(G.vs[edge.source]['pressure'] -   \
                            G.vs[edge.target]['pressure']) *  \
                        edge['conductance'] for edge in G.es]

        self._maxPDiff = maxPDiff
        self._meanPDiff = meanPDiff
        self._medianPDiff = medianPDiff

        return maxPDiff, meanPDiff, medianPDiff
Esempio n. 17
0
from pyamg.gallery import gauge_laplacian 
from pyamg import smoothed_aggregation_solver, rootnode_solver
from convergence_tools import print_cycle_history

if __name__ == '__main__':
    n = 100
    
    print "Test convergence for a simple 100x100 Grid, Gauge Laplacian"
    choice = input('\n Input Choice:\n' + \
               '1:  Run smoothed_aggregation_solver\n' + \
               '2:  Run rootnode_solver\n' )

    numpy.random.seed(625)
    A = gauge_laplacian(n, beta=0.001) 
    x = scipy.rand(A.shape[0]) + 1.0j*scipy.rand(A.shape[0])
    b = scipy.rand(A.shape[0]) + 1.0j*scipy.rand(A.shape[0])
    
    if choice == 1:
        sa = smoothed_aggregation_solver(A, smooth='energy')
    elif choice == 2:
        sa = rootnode_solver(A, smooth='energy')
    else:
        raise ValueError("Enter a choice of 1 or 2")

    resvec = []
    x = sa.solve(b, x0=x, maxiter=20, tol=1e-14, residuals=resvec)

    print_cycle_history(resvec, sa, verbose=True, plotting=True)


Esempio n. 18
0
    def solve(self, solver="lu", x0=None, tol=1.e-6):
        solver = solver.lower()
        sf = 1e30
        pores = self.network.pores
        A = self.csr_solver_matrix
        self.solver_matrix.set_csr_singular_rows_to_dirichlet(A)
        self.A = A

        mass_residual = 1.0

        if x0 is not None:
            self.sol[:] = x0

        if solver == "lu":
            lu_A = splu(A)

        elif solver == "amg":
            ml = pyamg.rootnode_solver(A, max_coarse=10)

        elif solver == "petsc":
            comm = MPI.COMM_SELF
            ksp = get_petsc_ksp(A=A * sf, ksptype="minres", tol=tol, max_it=1000)
            petsc_rhs = PETSc.Vec().createWithArray(self.rhs * sf, comm=comm)

        elif "trilinos" in solver:
            epetra_mat = matrix_scipy_to_epetra(A * sf)
            epetra_rhs = vector_numpy_to_epetra(self.rhs * sf)

            if "ml" in solver:
                epetra_prec = trilinos_ml_prec(epetra_mat)

        def inner_loop_solve(tol):
            if solver == "lu":
                self.sol[:] = lu_A.solve(self.rhs)

            elif solver == "amg":
                self.sol[:] = ml.solve(b=self.rhs, x0=self.sol, tol=tol, accel='gmres')

            elif solver == "petsc":
                ksp.setTolerances(rtol=tol)
                ksp.setFromOptions()
                petsc_sol = PETSc.Vec().createWithArray(self.sol, comm=comm)
                ksp.setInitialGuessNonzero(True)
                ksp.solve(petsc_rhs, petsc_sol)

                self.sol[:] = petsc_sol.getArray()

            elif "trilinos" in solver:
                epetra_sol = vector_numpy_to_epetra(self.sol)

                if "ml" in solver:
                    x = trilinos_solve(epetra_mat, epetra_rhs, epetra_prec, x=epetra_sol, tol=tol)
                else:
                    x = solve_aztec(epetra_mat, epetra_rhs, x=epetra_sol, tol=tol)
                self.sol[:] = x

            pores.p_w[:] = self.sol[:]  # This side-effect is required for the compute_mass_residual function
            pores.p_n[:] = pores.p_w + pores.p_c

        count = 0
        while (mass_residual > 1e-5) and (count < 100):
            count += 1
            inner_loop_solve(tol)
            mass_residual = self.compute_mass_residual(A, self.rhs, self.sol)
            logger.debug("Mass flux residual %e", mass_residual)
            if count == 99:
                logger.warn("Failed to converge. Residual %e. Falling back to mltrilinos solver", mass_residual)
                return self.solve(solver="mltrilinos") # Fall back to reliable solver

            tol /= 10.0

        if "ml" in solver:
            epetra_prec.DestroyPreconditioner();

        return np.copy(self.sol)
                                           presmoother=prepost,
                                           postsmoother=prepost,
                                           smooth=smooth,
                                           strength=('evolution', {'epsilon': evolution_theta, 'k': 2}))
    resvec = []
    x = ml.solve(b, x0=x0, maxiter=100, tol=1e-8, residuals=resvec)
    factors_evo[run] = (resvec[-1] / resvec[0])**(1.0 / len(resvec))
    complexity_evo[run] = ml.operator_complexity()
    nnz_evo[run] = A.nnz
    sizelist_evo[run] = A.shape[0]

    # Evolution strength measure
    ml = pyamg.rootnode_solver(A,
                               max_coarse=mcoarse,
                               coarse_solver='pinv2',
                               presmoother=prepost,
                               postsmoother=prepost,
                               smooth=smooth,
                               strength=('evolution', {'epsilon': evolution_theta, 'k': 2}))
    resvec = []
    x = ml.solve(b, x0=x0, maxiter=100, tol=1e-8, residuals=resvec)
    factors_evo_root[run] = (resvec[-1] / resvec[0])**(1.0 / len(resvec))
    complexity_evo_root[run] = ml.operator_complexity()
    nnz_evo_root[run] = A.nnz
    sizelist_evo_root[run] = A.shape[0]

    run += 1

# Print Problem Description
print("\nAMG Scalability Study for Ax = 0, x_init = rand\n")
print("Emphasis on Robustness of Evolution Strength ")
Esempio n. 20
0
def fixed_stress(gb, A, b, block_dof, full_dof, x0=None):
    """
    Fixed stress solver for Biot coupled with elasticity
    """
    tic = time.time()

    # Data loading step
    # Linear solver starts here
    nd = gb.dim_max()
    g = gb.grids_of_dimension(nd)[0]
    data = gb.node_props(g)
    num_cells = g.num_cells

    # Get indices of different dofs
    # full_dof contains the number of dofs per block. To get a global ordering, use
    global_dof = np.r_[0, np.cumsum(full_dof)]

    # split global variable
    block_u = block_dof[(g, "u")]
    block_p = block_dof[(g, "p")]
    block_lam_u = block_dof[((g, g), "lam_u")]
    if ((g, g), "lam_p") in block_dof:
        block_lam_p = block_dof[((g, g), "lam_p")]
        mortar_p_ind = np.arange(global_dof[block_lam_p],
                                 global_dof[block_lam_p + 1])
    else:  # if we don't have a mortar variable for pressure (non-permeable fractures)
        mortar_p_ind = np.array([], dtype=np.int)
    # Get the global displacement and pressure dofs
    el_ind = np.arange(global_dof[block_u], global_dof[block_u + 1])
    p_ind = np.arange(global_dof[block_p], global_dof[block_p + 1])
    mortar_el_ind = np.arange(global_dof[block_lam_u],
                              global_dof[block_lam_u + 1])

    num_mortar = full_dof[-1]

    # merge pressure and pressure mortar indices
    p_full_ind = np.hstack((p_ind, mortar_p_ind))
    rest_ind = np.hstack((el_ind, p_full_ind))

    # Extract submatrices
    A_rest_rest = A[rest_ind][:, rest_ind]
    A_rest_m = A[rest_ind][:, mortar_el_ind]
    A_m_rest = A[mortar_el_ind][:, rest_ind]

    A_m_m = A[mortar_el_ind, :][:, mortar_el_ind]

    b_el = b[el_ind]

    n = num_cells * nd

    solution = np.zeros_like(b)

    residuals = []

    def callback(r):
        residuals.append(r)

    # Preconditioning of the linear system, based on a Schur complement reduction to a
    # system in the elasticity variables.

    # Approximation of the inverse of A_m_m, by a diagonal matrix.
    # The quality of this for various configurations of the mortar variable is not clear.
    iA_m_m = sps.dia_matrix((1.0 / A_m_m.diagonal(), 0), A_m_m.shape)

    # Also create a factorization of the mortar variable. This is relatively cheap, so why not
    A_m_m_solve = sps.linalg.factorized(A_m_m)

    # Schur complement formulation, using the approximated inv(A_m_m)
    S = A_rest_rest - A_rest_m * iA_m_m * A_m_rest

    S_el = S[:, el_ind][el_ind, :]

    p_schur_ind = np.arange(el_ind.size, S.shape[0])

    S_p = S[:, p_schur_ind][p_schur_ind]

    S_el_p = S[el_ind][:, p_schur_ind]
    S_p_el = S[p_schur_ind][:, el_ind]

    # Create an AMG hierarchy
    amg_args = {
        'presmoother': ('gauss_seidel', {
            'sweep': 'symmetric',
            'iterations': 2
        }),
        'postsmoother': ('gauss_seidel', {
            'sweep': 'symmetric',
            'iterations': 2
        }),
    }
    #ml = pyamg.smoothed_aggregation_solver(S_el, symmetry='nonsymmetric', **amg_args)
    ml = pyamg.rootnode_solver(S_el, symmetry='nonsymmetric', **amg_args)
    print(ml)
    # Use as preconditioner

    solve_el = ml.aspreconditioner(cycle='W')

    biot_alpha = data[pp.PARAMETERS]['mech']['biot_alpha']
    rock_type = data[pp.PARAMETERS]['mech']['rock']

    stab_size = p_schur_ind.size
    stab_vec = (biot_alpha**2 / (2 *
                                 (2 * rock_type.MU / nd + rock_type.LAMBDA)) *
                np.ones(stab_size))
    stabilization = sps.dia_matrix((stab_vec, 0), shape=(stab_size, stab_size))

    solve_p = sps.linalg.factorized(S_p + stabilization)

    def solve_fixed_stress(r):
        r_p = r[p_schur_ind]
        dp = solve_p(r_p)
        r_el = r[el_ind] - S_el_p * dp

        d_el = solve_el(r_el)

        return np.hstack((d_el, dp))

    def precond_schur(r):
        # Mortar residual
        rm = r[mortar_el_ind]
        # Residual for the elasticity is the local one, plus the mapping of the mortar residual
        r_rest = r[rest_ind] - A_rest_m * A_m_m_solve(rm)
        # Solve, using specified solver
        du = solve_fixed_stress(r_rest)
        # Map back to mortar residual
        dm = A_m_m_solve(rm - A_m_rest * du)
        return np.hstack((du, dm))

    max_it = 1000

    M = sps.linalg.LinearOperator(A.shape, precond_schur)

    # Inital guess
    if x0 is None:
        x0 = np.zeros(A.shape[1])

    solution, info = sps.linalg.gmres(A,
                                      b,
                                      M=M,
                                      x0=x0,
                                      restart=max_it,
                                      callback=callback,
                                      maxiter=max_it,
                                      tol=1e-11)

    if len(residuals) > 0:
        print("Linear solver residual: ", residuals[-1])
    print("Linear solver iterations: ", len(residuals))
    print('Linear solver time: ' + str(time.time() - tic))
    return solution, info, residuals
Esempio n. 21
0
from cvoutput import *
from convergence_tools import print_cycle_history

##
# Run Rotated Anisotropic Diffusion
n = 10
nx = n
ny = n
stencil = diffusion_stencil_2d(type='FE',epsilon=0.001,theta=scipy.pi/3)
A = stencil_grid(stencil, (nx,ny), format='csr')
numpy.random.seed(625)
x = scipy.rand(A.shape[0])
b = A*scipy.rand(A.shape[0])

ml = rootnode_solver(A, strength=('evolution', {'epsilon':2.0}), 
                    smooth=('energy', {'degree':2}), max_coarse=10)
resvec = []
x = ml.solve(b, x0=x, maxiter=20, tol=1e-14, residuals=resvec)
print_cycle_history(resvec, ml, verbose=True, plotting=False)

##
# Write ConnectionViewer files for multilevel hierarchy ml
xV,yV = numpy.meshgrid(numpy.arange(0,ny,dtype=float),numpy.arange(0,nx,dtype=float))
Verts = numpy.concatenate([[xV.ravel()],[yV.ravel()]],axis=0).T
outputML("test", Verts, ml)


print "\n\nOutput files for matrix stencil visualizations in ConnectionViewer are: \n  \
test_A*.mat \n  test_fine*.marks \n  test_coarse*.marks \n  \
test_R*.mat \n  test_P*.mat \nwhere \'*\' is the level number"
##
Esempio n. 22
0
# Illustrates the selection of aggregates in AMG based on smoothed aggregation

import numpy
from pyamg import rootnode_solver
from pyamg.gallery import load_example

data = load_example('unit_square')

A = data['A'].tocsr()                        # matrix
V = data['vertices'][:A.shape[0]]            # vertices of each variable
E = numpy.vstack((A.tocoo().row,A.tocoo().col)).T  # edges of the matrix graph

# Use Root-Node Solver
mls = rootnode_solver(A, max_levels=2, max_coarse=1, keep=True)

# AggOp[i,j] is 1 iff node i belongs to aggregate j
AggOp = mls.levels[0].AggOp

# determine which edges lie entirely inside an aggregate
# AggOp.indices[n] is the aggregate to which vertex n belongs
inner_edges = AggOp.indices[E[:,0]] == AggOp.indices[E[:,1]]  
outer_edges = -inner_edges

# Grab the root-nodes (i.e., the C/F splitting)
Cpts = mls.levels[0].Cpts
Fpts = mls.levels[0].Fpts

from draw import lineplot
from pylab import figure, axis, scatter, show, title

##
            smooth=smooth,
            strength=("evolution", {"epsilon": evolution_theta, "k": 2}),
        )
        resvec = []
        x = ml.solve(b, x0=x0, maxiter=100, tol=1e-8, residuals=resvec)
        factors_ode[run] = (resvec[-1] / resvec[0]) ** (1.0 / len(resvec))
        complexity_ode[run] = ml.operator_complexity()
        nnz_ode[run] = A.nnz
        sizelist_ode[run] = A.shape[0]

        # Evolution strength measure
        ml = rootnode_solver(
            A,
            max_coarse=mcoarse,
            coarse_solver="pinv2",
            presmoother=prepost,
            postsmoother=prepost,
            smooth=smooth,
            strength=("evolution", {"epsilon": evolution_theta, "k": 2}),
        )
        resvec = []
        x = ml.solve(b, x0=x0, maxiter=100, tol=1e-8, residuals=resvec)
        factors_ode_root[run] = (resvec[-1] / resvec[0]) ** (1.0 / len(resvec))
        complexity_ode_root[run] = ml.operator_complexity()
        nnz_ode_root[run] = A.nnz
        sizelist_ode_root[run] = A.shape[0]

        run += 1

    # Print Problem Description
    print "\nAMG Scalability Study for Ax = 0, x_init = rand\n"
Esempio n. 24
0
print("Test convergence for a 200x200 Grid, Linearized Elasticity Problem")
choice = input('\n Input Choice:\n' +
               '1:  Run smoothed_aggregation_solver\n' +
               '2:  Run rootnode_solver\n')

# Create matrix and candidate vectors.  B has 3 columns, representing
# rigid body modes of the mesh. B[:,0] and B[:,1] are translations in
# the X and Y directions while B[:,2] is a rotation.
A, B = pyamg.gallery.linear_elasticity((200, 200), format='bsr')

# Construct solver using AMG based on Smoothed Aggregation (SA)
choice = int(choice)
if choice == 1:
    ml = pyamg.smoothed_aggregation_solver(A, B=B, smooth='energy')
elif choice == 2:
    ml = pyamg.rootnode_solver(A, B=B, smooth='energy')
else:
    raise ValueError("Enter a choice of 1 or 2")

# Display hierarchy information
print(ml)

# Create random right hand side
b = np.random.rand(A.shape[0], 1)

# Solve Ax=b
residuals = []
x = ml.solve(b, tol=1e-10, residuals=residuals)
print("Number of iterations:  {}d\n".format(len(residuals)))

# Output convergence
Esempio n. 25
0
    def get(self,
            k: int,
            heuristic: str,
            randomization: str,
            density: float = None,
            **kwargs) -> Subspace:
        """
        Compute a subspace in two levels, a first one obtained via an algebraic multi-grid method, and the second one of
        random type. The resulting subspace is then in the form of a product.

        :param k: Number of approximate eigen-vectors to compute.
        :param heuristic: Name of the algebraic multi-grid heuristic used to construct the hierarchy.
        :param randomization: Name of the random distribution to use for the second level projection.
        :param density: If provided, the random operator is sparse with given density.
        :param kwargs: complementary arguments for algebraic multi-grid construction, see PyAMG library for details.
        """
        # Setup multi-grid hierarchical structure with corresponding heuristic
        if heuristic == 'ruge_stuben':
            amg = pyamg.ruge_stuben_solver(self.linear_op.mat.tocsr(),
                                           max_levels=2,
                                           **kwargs)

        elif heuristic == 'smoothed_aggregated':
            amg = pyamg.smoothed_aggregation_solver(self.linear_op.mat.tocsr(),
                                                    max_levels=2,
                                                    **kwargs)

        elif heuristic == 'rootnode':
            amg = pyamg.rootnode_solver(self.linear_op.mat.tocsr(),
                                        max_levels=2,
                                        **kwargs)
        else:
            raise SubspaceError(
                'Algebraic multi-grid heuristic {} unknown.'.format(heuristic))

        self.P = Subspace(amg.levels[0].P)

        G = None

        _, k_ = self.P.shape

        if k > k_:
            warnings.warn(
                'Random restriction size superior to coarse operator size, hence truncated.'
            )
            k = k_

        # Sanitize random distribution argument
        if randomization not in ['gaussian']:
            raise SubspaceError(
                'Randomization name {} unknown.'.format(heuristic))

        # Initialize subspace in dok format to allow easy update
        if randomization == 'gaussian':
            if density is not None:
                rvs = scipy.stats.norm().rvs
                G = Subspace(
                    scipy.sparse.random(k_, k, density=density, data_rvs=rvs))
            else:
                G = Subspace(numpy.random.randn(k_, k))

        return self.P @ G
Esempio n. 26
0
    def solve(self, method, **kwargs):
        """Solves the linear system A x = b for the vector of unknown pressures
        x, either using a direct solver or an iterative AMG solver. From the
        pressures, the flow field is computed.
        INPUT: method: This can be either 'direct' or 'iterative'
               **kwargs 
               precision: The accuracy to which the ls is to be solved. If not 
                          supplied, machine accuracy will be used.
               maxiter: The maximum number of iterations. The default value for
                        the iterative solver is 250.
        OUTPUT: None - G is modified in place.
        """
                
        b = self._b
        G = self._G
        htt2htd = self._P.tube_to_discharge_hematocrit
        
        A = self._A.tocsr()
        if method == 'direct':
            linalg.use_solver(useUmfpack=True)
            x = linalg.spsolve(A, b)
        elif method == 'iterative':
            if kwargs.has_key('precision'):
                eps = kwargs['precision']
            else:
                eps = self._eps
            if kwargs.has_key('maxiter'):
                maxiter = kwargs['maxiter']
            else:
                maxiter = 250
            AA = pyamg.smoothed_aggregation_solver(A, max_levels=10, max_coarse=500)
            x = abs(AA.solve(self._b, x0=None, tol=eps, accel='cg', cycle='V', maxiter=maxiter))
            # abs required, as (small) negative pressures may arise
        elif method == 'iterative2':
         # Set linear solver
             ml = rootnode_solver(A, smooth=('energy', {'degree':2}), strength='evolution' )
             M = ml.aspreconditioner(cycle='V')
             # Solve pressure system
             x,info = gmres(A, self._b, tol=self._eps, maxiter=50, M=M)
             if info != 0:
                 print('ERROR in Solving the Matrix')

        G.vs['pressure'] = x
        self._x = x
        conductance = self._conductance
        G.es['flow'] = [abs(G.vs[edge.source]['pressure'] -   \
                            G.vs[edge.target]['pressure']) *  \
                        conductance[i] for i, edge in enumerate(G.es)]
        for v in G.vs:
            v['pressure']=v['pressure']/vgm.units.scaling_factor_du('mmHg',G['defaultUnits'])
        if self._withRBC:
            for e in G.es:
                dischargeHt = min(htt2htd(e['htt'], e['diameter'], self._invivo), 1.0)
	        e['v']=dischargeHt/e['htt']*e['flow']/(0.25*np.pi*e['diameter']**2)
        else:
            for e in G.es:
	        e['v']=e['flow']/(0.25*np.pi*e['diameter']**2)
        
        #Convert 'pBC' from default Units to mmHg
        pBCneNone=G.vs(pBC_ne=None).indices
        if 'diamCalcEff' in G.es.attribute_names():
            del(G.es['diamCalcEff'])

        if 'effResistance' in G.es.attribute_names():
            del(G.es['effResistance'])

        if 'conductance' in G.es.attribute_names():
            del(G.es['conductance'])

        if 'resistance' in G.es.attribute_names():
            del(G.es['resistance'])

        G.vs[pBCneNone]['pBC']=np.array(G.vs[pBCneNone]['pBC'])*(1/vgm.units.scaling_factor_du('mmHg',G['defaultUnits']))

        vgm.write_pkl(G, 'G_final.pkl')
        vgm.write_vtp(G, 'G_final.vtp',False)

	#Write Output
	sampledict={}
        for eprop in ['flow', 'v']:
            if not eprop in sampledict.keys():
                sampledict[eprop] = []
            sampledict[eprop].append(G.es[eprop])
        for vprop in ['pressure']:
            if not vprop in sampledict.keys():
                sampledict[vprop] = []
            sampledict[vprop].append(G.vs[vprop])

	g_output.write_pkl(sampledict, 'sampledict.pkl')
Esempio n. 27
0
    def update(self, thickness_edge, vc, c, g):

        self.thicknessInv[:] = 1. / thickness_edge

        ## Construct the blocks
        self.A11 = self.AC.multiply(self.thicknessInv)
        self.A11 *= self.mSkewgrad_td

        self.A12 = self.AMC.multiply(self.thicknessInv)
        self.A12 *= self.mGrad_n_n
        self.A12 += self.AC.multiply(self.thicknessInv) * self.GN
        self.A12 *= 0.5

        self.A21 = self.AD.multiply(self.thicknessInv)
        self.A21 *= self.SN
        self.A21 += self.AMD.multiply(self.thicknessInv) * self.mSkewgrad_td
        self.A21 *= 0.5

        self.A22 = self.AD.multiply(self.thicknessInv)
        self.A22 *= self.mGrad_n_n

        #self.A11 = self.A11.tolil( )
        #self.A22 = self.A22.tolil( )
        if c.on_a_global_sphere:
            self.A11[0, 0] = -2 * np.sqrt(3.) / thickness_edge[0]
            self.A22[0, 0] = -2 * np.sqrt(3.) / thickness_edge[0]
        else:
            self.A11[g.cellBoundary - 1,
                     g.cellBoundary - 1] = -2 * np.sqrt(3.) / thickness_edge[0]
            self.A22[0, 0] = -2 * np.sqrt(3.) / thickness_edge[0]
        #self.A11 = self.A11.tocsr( )
        #self.A22 = self.A22.tocsr( )

        if c.linear_solver is 'lu':
            # Convert the matrices to CSC for better performance
            self.A11 = self.A11.tocsc()
            self.A22 = self.A22.tocsc()

        elif c.linear_solver is 'amg':
            self.A11 *= -1
            self.A12 *= -1
            self.A21 *= -1
            self.A22 *= -1

            B11 = np.ones((self.A11.shape[0], 1), dtype=self.A11.dtype)
            BH11 = B11.copy()
            self.A11_solver = rootnode_solver(self.A11, B=B11, BH=BH11,
                strength=('evolution', {'epsilon': 2.0, 'k': 2, 'proj_type': 'l2'}),
                smooth=('energy', {'weighting': 'local', 'krylov': 'cg', 'degree': 2, 'maxiter': 3}),
                improve_candidates=[('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 4}), \
                                    None, None, None, None, None, None, None, None, None, None, \
                                    None, None, None, None],
                aggregate="standard",
                presmoother=('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}),
                postsmoother=('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}),
                max_levels=15,
                max_coarse=300,
                coarse_solver="pinv")

            B22 = np.ones((self.A22.shape[0], 1), dtype=self.A22.dtype)
            BH22 = B22.copy()
            self.A22_solver = rootnode_solver(self.A22, B=B22, BH=BH22,
                strength=('evolution', {'epsilon': 2.0, 'k': 2, 'proj_type': 'l2'}),
                smooth=('energy', {'weighting': 'local', 'krylov': 'cg', 'degree': 2, 'maxiter': 3}),
                improve_candidates=[('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 4}), \
                                    None, None, None, None, None, None, None, None, None, None, \
                                    None, None, None, None],
                aggregate="standard",
                presmoother=('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}),
                postsmoother=('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}),
                max_levels=15,
                max_coarse=300,
                coarse_solver="pinv")

        elif c.linear_solver is 'amgx':
            self.d_A11.upload_CSR(self.A11)
            self.d_A22.upload_CSR(self.A22)
            self.slv11.setup(self.d_A11)
            self.slv22.setup(self.d_A22)

        else:
            raise ValueError("Invalid solver choice.")
Esempio n. 28
0
# Illustrates the selection of aggregates in AMG based on smoothed aggregation

import numpy
from pyamg import rootnode_solver
from pyamg.gallery import load_example

data = load_example('unit_square')

A = data['A'].tocsr()  # matrix
V = data['vertices'][:A.shape[0]]  # vertices of each variable
E = numpy.vstack((A.tocoo().row, A.tocoo().col)).T  # edges of the matrix graph

# Use Root-Node Solver
mls = rootnode_solver(A, max_levels=2, max_coarse=1, keep=True)

# AggOp[i,j] is 1 iff node i belongs to aggregate j
AggOp = mls.levels[0].AggOp

# determine which edges lie entirely inside an aggregate
# AggOp.indices[n] is the aggregate to which vertex n belongs
inner_edges = AggOp.indices[E[:, 0]] == AggOp.indices[E[:, 1]]
outer_edges = -inner_edges

# Grab the root-nodes (i.e., the C/F splitting)
Cpts = mls.levels[0].Cpts
Fpts = mls.levels[0].Fpts

from draw import lineplot
from pylab import figure, axis, scatter, show, title

##
Esempio n. 29
0
    def __init__(self, A, linear_solver, env):

        if linear_solver is 'lu':
            self.A = A.tocsc()
            self.lu = splu(self.A)
        elif linear_solver is 'cg':
            self.A = A.tocsr()
        elif linear_solver in ['cudaCG']:
            self.A = A.tocsr()
            self.dData = env.cuda.to_device(self.A.data)
            self.dPtr = env.cuda.to_device(self.A.indptr)
            self.dInd = env.cuda.to_device(self.A.indices)
            self.cuSparseDescr = env.cuSparse.matdescr()
        elif linear_solver in ['cudaPCG']:
            self.A = A.tocsr()
            self.Adescr = env.cuSparse.matdescr()
            self.Adata = env.cuda.to_device(self.A.data)
            self.Aptr = env.cuda.to_device(self.A.indptr)
            self.Aind = env.cuda.to_device(self.A.indices)

            A_t = self.A.copy()
            A_t = -A_t  # Make it positive definite
            A_t.data = np.where(A_t.nonzero()[0] >= A_t.nonzero()[1], A_t.data,
                                0.)
            A_t.eliminate_zeros()
            A_t_descr = env.cuSparse.matdescr(matrixtype='S', fillmode='L')
            info = env.cuSparse.csrsv_analysis(trans='N', m=A_t.shape[0], nnz=A_t.nnz, \
                                       descr=A_t_descr, csrVal=A_t.data, \
                                       csrRowPtr=A_t.indptr, csrColInd=A_t.indices)
            env.cuSparse.csric0(trans='N', m=A_t.shape[0], \
                        descr=A_t_descr, csrValM=A_t.data, csrRowPtrA=A_t.indptr,\
                        csrColIndA=A_t.indices, info=info)

            self.L = A_t
            self.Lmv_descr = env.cuSparse.matdescr()
            #        self.Lsv_descr = cuSparse.matdescr(matrixtype='T', fillmode='L')
            self.Lsv_descr = env.cuSparse.matdescr(matrixtype='T')
            self.Ldata = env.cuda.to_device(self.L.data)
            self.Lptr = env.cuda.to_device(self.L.indptr)
            self.Lind = env.cuda.to_device(self.L.indices)
            self.Lsv_info = env.cuSparse.csrsv_analysis(trans='N', m=self.L.shape[0], \
                    nnz=self.L.nnz,  descr=self.Lsv_descr, csrVal=self.Ldata, \
                    csrRowPtr=self.Lptr, csrColInd=self.Lind)

            self.LT = self.L.transpose()
            self.LT.tocsr()
            self.LTmv_descr = env.cuSparse.matdescr()
            #            self.LTsv_descr = env.cuSparse.matdescr(matrixtype='T', fillmode='U')
            self.LTsv_descr = env.cuSparse.matdescr()
            self.LTdata = env.cuda.to_device(self.LT.data)
            self.LTptr = env.cuda.to_device(self.LT.indptr)
            self.LTind = env.cuda.to_device(self.LT.indices)
            self.LTsv_info = env.cuSparse.csrsv_analysis(trans='T', m=self.L.shape[0], \
                    nnz=self.L.nnz,  descr=self.Lsv_descr, csrVal=self.Ldata, \
                    csrRowPtr=self.Lptr, csrColInd=self.Lind)

        elif linear_solver is 'pcg':
            self.A = A.tocsr()
            A_t = -self.D2s

        elif linear_solver is 'amg':

            self.A = A.tocsr()
            self.A_spd = self.A.copy()
            self.A_spd = -self.A_spd
            self.B = np.ones((self.A_spd.shape[0], 1), dtype=self.A_spd.dtype)
            self.BH = self.B.copy()

            if self.A_spd.shape[0] in [40962, 163842, 655362]:
                self.A_amg = rootnode_solver(self.A_spd, B=self.B, BH=self.BH,
                    strength=('evolution', {'epsilon': 2.0, 'k': 2, 'proj_type': 'l2'}),
                    smooth=('energy', {'weighting': 'local', 'krylov': 'cg', 'degree': 2, 'maxiter': 3}),
                    improve_candidates=[('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 4}), \
                                        None, None, None, None, None, None, None, None, None, None, \
                                        None, None, None, None],
                    aggregate="standard",
                    presmoother=('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}),
                    postsmoother=('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}),
                    max_levels=15,
                    max_coarse=300,
                    coarse_solver="pinv")
            elif self.A_spd.shape[0] in [81920, 327680, 1310720, 5242880]:
                self.A_amg = rootnode_solver(self.A_spd, B=self.B, BH=self.BH,
                    strength=('evolution', {'epsilon': 4.0, 'k': 2, 'proj_type': 'l2'}),
                    smooth=('energy', {'weighting': 'local', 'krylov': 'cg', 'degree': 2, 'maxiter': 3}),
                    improve_candidates=[('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 4}), \
                                        None, None, None, None, None, None, None, None, None, None, \
                                        None, None, None, None],
                    aggregate="standard",
                    presmoother=('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}),
                    postsmoother=('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}),
                    max_levels=15,
                    max_coarse=300,
                    coarse_solver="pinv")
            elif self.A_spd.shape[0] in [2621442]:
                self.A_amg = rootnode_solver(self.A_spd, B=self.B, BH=self.BH,
                    strength=('evolution', {'epsilon': 4.0, 'k': 2, 'proj_type': 'l2'}),
                    smooth=('energy', {'weighting': 'local', 'krylov': 'cg', 'degree': 3, 'maxiter': 4}),
                    improve_candidates=[('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 4}), \
                                        None, None, None, None, None, None, None, None, None, None, \
                                        None, None, None, None],
                    aggregate="standard",
                    presmoother=('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}),
                    postsmoother=('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}),
                    max_levels=15,
                    max_coarse=300,
                    coarse_solver="pinv")

            else:
                print("Unknown matrix. Using a generic AMG solver")

                self.A_amg = rootnode_solver(self.A_spd, B=self.B, BH=self.BH,
                    strength=('evolution', {'epsilon': 2.0, 'k': 2, 'proj_type': 'l2'}),
                    smooth=('energy', {'weighting': 'local', 'krylov': 'cg', 'degree': 2, 'maxiter': 3}),
                    improve_candidates=[('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 4}), \
                                        None, None, None, None, None, None, None, None, None, None, \
                                        None, None, None, None],
                    aggregate="standard",
                    presmoother=('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}),
                    postsmoother=('block_gauss_seidel', {'sweep': 'symmetric', 'iterations': 1}),
                    max_levels=15,
                    max_coarse=300,
                    coarse_solver="pinv")

        elif linear_solver is 'amgx':
            import pyamgx

            pyamgx.initialize()

            hA = A.tocsr()
            if hA.nnz * 1. / hA.shape[0] > 5.5:  # Primary mesh
                AMGX_CONFIG_FILE_NAME = 'amgx_config/PCGF_CLASSICAL_AGGRESSIVE_PMIS_JACOBI.json'
            if hA.nnz * 1. / hA.shape[0] < 5.5:  # Dual mesh
                AMGX_CONFIG_FILE_NAME = 'amgx_config/PCGF_CLASSICAL_AGGRESSIVE_PMIS.json'
            else:
                print(
                    'Error: cannot determine primary or dual mesh, not sure which config to use.'
                )

            cfg = pyamgx.Config().create_from_file(AMGX_CONFIG_FILE_NAME)
            rsc = pyamgx.Resources().create_simple(cfg)
            mode = 'dDDI'

            # Create solver:
            self.amgx = pyamgx.Solver().create(rsc, cfg, mode)

            # Create matrices and vectors:
            d_A = pyamgx.Matrix().create(rsc, mode)
            self.d_x = pyamgx.Vector().create(rsc, mode)
            self.d_b = pyamgx.Vector().create(rsc, mode)

            d_A.upload(hA.indptr, hA.indices, hA.data)

            # Setup and solve system:
            self.amgx.setup(d_A)

            ## Clean up:
            #A.destroy()
            #x.destroy()
            #b.destroy()
            #self.amgx.destroy()
            #rsc.destroy()
            #cfg.destroy()

            #pyamgx.finalize()
        else:
            raise ValueError("Invalid solver choice.")
                                             'epsilon': evolution_theta,
                                             'k': 2
                                         }))
        resvec = []
        x = ml.solve(b, x0=x0, maxiter=100, tol=1e-8, residuals=resvec)
        factors_ode[run] = (resvec[-1] / resvec[0])**(1.0 / len(resvec))
        complexity_ode[run] = ml.operator_complexity()
        nnz_ode[run] = A.nnz
        sizelist_ode[run] = A.shape[0]

        # Evolution strength measure
        ml = rootnode_solver(A,
                             max_coarse=mcoarse,
                             coarse_solver='pinv2',
                             presmoother=prepost,
                             postsmoother=prepost,
                             smooth=smooth,
                             strength=('evolution', {
                                 'epsilon': evolution_theta,
                                 'k': 2
                             }))
        resvec = []
        x = ml.solve(b, x0=x0, maxiter=100, tol=1e-8, residuals=resvec)
        factors_ode_root[run] = (resvec[-1] / resvec[0])**(1.0 / len(resvec))
        complexity_ode_root[run] = ml.operator_complexity()
        nnz_ode_root[run] = A.nnz
        sizelist_ode_root[run] = A.shape[0]

        run += 1

    # Print Problem Description
    print "\nAMG Scalability Study for Ax = 0, x_init = rand\n"
Esempio n. 31
0
space = LagrangeFiniteElementSpace(mesh, p=p)

bc0 = DirichletBC(space, pde.dirichlet, threshold=pde.is_dirichlet_boundary)
bc1 = NeumannBC(space, pde.neumann, threshold=pde.is_neumann_boundary)

uh = space.function(dim=2)  # (gdof, 2) and vector fem function uh[i, j]
A = space.linear_elasticity_matrix(pde.mu, pde.lam)  # (2*gdof, 2*gdof)
F = space.source_vector(pde.source, dim=2)
F = bc1.apply(F)
A, F = bc0.apply(A, F, uh)

if False:
    uh.T.flat[:] = spsolve(A, F)  # (2, gdof ).flat
else:
    ml = pyamg.rootnode_solver(A)  # AMG solver
    M = ml.aspreconditioner(cycle='V')  # preconditioner
    start = timer()
    uh.T.flat[:], info = cg(A, F, tol=1e-8, maxiter=100, M=M)  # solve with CG
    end = timer()
    print('time:', end - start)

# 原始的网格
mesh.add_plot(plt)

# 变形的网格
mesh.node += scale * uh
mesh.add_plot(plt)

plt.show()
Esempio n. 32
0
    
print "Test convergence for a simple 200x200 Grid, Linearized Elasticity Problem"
choice = input('\n Input Choice:\n' + \
           '1:  Run smoothed_aggregation_solver\n' + \
           '2:  Run rootnode_solver\n' )

# Create matrix and candidate vectors.  B has 3 columns, representing 
# rigid body modes of the mesh. B[:,0] and B[:,1] are translations in 
# the X and Y directions while B[:,2] is a rotation.
A,B = linear_elasticity((200,200), format='bsr')

# Construct solver using AMG based on Smoothed Aggregation (SA)
if choice == 1:
    mls = smoothed_aggregation_solver(A, B=B, smooth='energy')
elif choice == 2:
    mls = rootnode_solver(A, B=B, smooth='energy')
else:
    raise ValueError("Enter a choice of 1 or 2")

# Display hierarchy information
print mls

# Create random right hand side
b = scipy.rand(A.shape[0],1)

# Solve Ax=b
residuals = []
x = mls.solve(b, tol=1e-10, residuals=residuals)
print "Number of iterations:  %d\n"%len(residuals)

# Output convergence
Esempio n. 33
0
def test_size(size, test_config):
    baseline_errors_div_diff = []
    operator_complexities = []

    fp_threshold = test_config.fp_threshold
    strength = test_config.strength
    presmoother = test_config.presmoother
    postsmoother = test_config.postsmoother
    coarse_solver = test_config.coarse_solver

    cycle = test_config.cycle
    splitting = test_config.splitting
    num_runs = test_config.num_runs
    dist = test_config.dist
    max_levels = test_config.max_levels
    iterations = test_config.iterations
    load_data = test_config.load_data

    block_periodic = False
    root_num_blocks = 1

    if load_data:
        if dist == 'lognormal_laplacian_periodic':
            As = np.load(
                f"test_data_dir/delaunay_periodic_logn_num_As_{100}_num_points_{size}.npy"
            )
        elif dist == 'lognormal_complex_fem':
            As = np.load(
                f"test_data_dir/fe_hole_logn_num_As_{100}_num_points_{size}.npy"
            )
        else:
            raise NotImplementedError()

    for i in tqdm(range(num_runs)):
        if load_data:
            A = As[i]
        else:
            A = generate_A(size, dist, block_periodic, root_num_blocks)

        num_unknowns = A.shape[0]
        x0 = np.random.normal(loc=0.0, scale=1.0, size=num_unknowns)
        b = np.zeros((A.shape[0]))

        baseline_residuals = []

        if splitting is 'CR' or splitting[0] is 'CR':
            baseline_solver = cr_solver(A,
                                        presmoother=presmoother,
                                        postsmoother=postsmoother,
                                        keep=True,
                                        max_levels=max_levels,
                                        CF=splitting,
                                        coarse_solver=coarse_solver)
        elif splitting is 'SA':
            baseline_solver = smoothed_aggregation_solver(
                A,
                strength=strength,
                presmoother=presmoother,
                postsmoother=postsmoother,
                max_levels=max_levels,
                keep=True,
                coarse_solver=coarse_solver)
        elif splitting is 'rootnode':
            baseline_solver = rootnode_solver(A,
                                              strength=strength,
                                              presmoother=presmoother,
                                              postsmoother=postsmoother,
                                              max_levels=max_levels,
                                              keep=True,
                                              coarse_solver=coarse_solver)
        else:
            baseline_solver = ruge_stuben_solver(A,
                                                 strength=strength,
                                                 interpolation='direct',
                                                 presmoother=presmoother,
                                                 postsmoother=postsmoother,
                                                 keep=True,
                                                 max_levels=max_levels,
                                                 CF=splitting,
                                                 coarse_solver=coarse_solver)

        operator_complexities.append(baseline_solver.operator_complexity())

        _ = baseline_solver.solve(b,
                                  x0=x0,
                                  tol=0.0,
                                  maxiter=iterations,
                                  cycle=cycle,
                                  residuals=baseline_residuals)
        baseline_residuals = np.array(baseline_residuals)
        baseline_residuals = baseline_residuals[
            baseline_residuals > fp_threshold]
        baseline_factor = baseline_residuals[-1] / baseline_residuals[-2]
        baseline_errors_div_diff.append(baseline_factor)

    baseline_errors_div_diff = np.array(baseline_errors_div_diff)
    baseline_errors_div_diff_mean = np.mean(baseline_errors_div_diff)
    baseline_errors_div_diff_std = np.std(baseline_errors_div_diff)

    operator_complexity_mean = np.mean(operator_complexities)
    operator_complexity_std = np.std(operator_complexities)

    if type(splitting) == tuple:
        splitting_str = splitting[0] + '_' + '_'.join(
            [f'{key}_{value}' for key, value in splitting[1].items()])
    else:
        splitting_str = splitting
    results_file = open(
        f"results/baseline/{dist}_{num_unknowns}_cycle_{cycle}_max_levels_{max_levels}_split_{splitting_str}_results.txt",
        'w')
    print(f"cycle: {cycle}, max levels: {max_levels}", file=results_file)

    print(
        f"asymptotic error factor baseline: {baseline_errors_div_diff_mean:.4f} ± {baseline_errors_div_diff_std:.5f}",
        file=results_file)

    print(f"num unknowns: {num_unknowns}")
    print(
        f"asymptotic error factor baseline: {baseline_errors_div_diff_mean:.4f} ± {baseline_errors_div_diff_std:.5f}"
    )

    print(
        f"operator complexity: {operator_complexity_mean:.4f} ± {operator_complexity_std:.5f}"
    )
    print(
        f"operator complexity: {operator_complexity_mean:.4f} ± {operator_complexity_std:.5f}",
        file=results_file)

    results_file.close()