Source code for naginterfaces.library.examples.sparseig.feast_poly_gen_solve_ex

#!/usr/bin/env python3
"``naginterfaces.library.sparseig.feast_poly_gen_solve`` Python Example."

# NAG Copyright 2020.

# pylint: disable=invalid-name,too-many-arguments,too-many-locals

import math
import numpy as np

from naginterfaces.library import machine, sparse, sparseig
from naginterfaces.base import utils as b_utils

def contour(handle):
    """ Define the custom contour and create the nodes and weights """
    zedge = np.array([-1.5 - 0.5j, 0.5 + 1.5j])
    tedge = np.array([100, 0], dtype=b_utils.EngineIntNumPyType)
    nedge = np.array([20, 10], dtype=b_utils.EngineIntNumPyType)
    sparseig.feast_custom_contour(handle, nedge, tedge, zedge)
    return handle

def input_data():
    """ Get input data for the problem """

    # The degree of the polynomial and the matrix size
    deg = 2
    n = 4

    # The 3 columns of a, irowa and icola correspond to the matrices
    # A0, A1 and A2, stored in sparse CS format. nnza contains the
    # number of nonzero elements in A0, A1 and A2
    nnza = np.array([5, 6, 4], dtype=b_utils.EngineIntNumPyType)
    a = np.array([
        [7.5 + 0.0j, 0.0 + 1.0j, 1.0 + 0.0j],
        [-1.7 + 0.0j, 0.0 + 1.2j, 1.7 + 0.0j],
        [0.0 + 0.4j, 0.0 + 2.9j, 0.2 + 0.0j],
        [0.2 + 0.0j, 0.0 - 3.4j, -5.8 + 0.0j],
        [-1.6 + 0.0j, 0.0 + 0.1j, 0.0 + 0.0j],
        [0.0 + 0.0j, 0.0 + 1.2j, 0.0 + 0.0j]
    ])

    irowa = np.array([
        [1, 1, 1],
        [2, 1, 2],
        [3, 2, 3],
        [3, 2, 4],
        [4, 3, 0],
        [0, 4, 0]
    ]).astype(int)

    icola = np.array([
        [2, 1, 1],
        [1, 3, 2],
        [3, 2, 3],
        [4, 4, 4],
        [2, 3, 0],
        [0, 4, 0]
    ]).astype(int)
    return deg, n, nnza, a, irowa, icola

def form_matrix_pencil(ze, deg, n, nnza, a, irowa, icola, conjg):
    """ Form the sparse matrix sum ze^i A_i or (sum ze^i A_i)^H """
    nnzsum = np.sum(nnza)
    az_tmp = np.zeros(nnzsum, dtype=np.complex128)
    irowz_tmp = np.zeros(nnzsum, dtype=b_utils.EngineIntNumPyType)
    icolz_tmp = np.zeros(nnzsum, dtype=b_utils.EngineIntNumPyType)
    ind = 0
    for i in range(deg+1):
        if conjg:
            az_tmp[ind:ind+nnza[i]] = np.conj((ze**i)*a[0:nnza[i], i])
            irowz_tmp[ind:ind+nnza[i]] = icola[0:nnza[i], i]
            icolz_tmp[ind:ind+nnza[i]] = irowa[0:nnza[i], i]
        else:
            az_tmp[ind:ind+nnza[i]] = (ze**i)*a[0:nnza[i], i]
            irowz_tmp[ind:ind+nnza[i]] = irowa[0:nnza[i], i]
            icolz_tmp[ind:ind+nnza[i]] = icola[0:nnza[i], i]
        ind = ind + nnza[i]
    # Sort elements into correct coordinate storage format
    az, irowz, icolz, _ = sparse.complex_gen_sort(
        n, az_tmp, irowz_tmp, icolz_tmp, 'S', 'R',
    )
    return az, irowz, icolz

def incomplete_lu(az, irowz, icolz, n):
    """ Form the incomplete LU factorization of a sparse matrix """
    nnaz = np.size(az)
    az = np.concatenate((az, np.zeros(2*nnaz)))
    irowz = np.concatenate((
        irowz,
        np.zeros(2*nnaz, dtype=b_utils.EngineIntNumPyType)
    ))
    icolz = np.concatenate((
        icolz,
        np.zeros(2*nnaz, dtype=b_utils.EngineIntNumPyType)
    ))
    az, irowz, icolz, ipivp, ipivq, istr, idiag, _, _ \
        = sparse.complex_gen_precon_ilu(
            nnaz, az, irowz, icolz, n,
            0, 0.0, 'P', 'N',
        )
    return az, irowz, icolz, ipivp, ipivq, istr, idiag

def solve_lin_sys(
        nnz_az, az, irowz, icolz, ipivp, ipivq, istr,
        idiag, y,
):
    """ Solve a sparse linear system """
    n = np.size(y, 0)
    m0 = np.size(y, 1)
    w = np.zeros(n, dtype=np.complex128)
    for i in range(m0):
        w[0:n] = y[0:n, i]
        y[0:n, i] = 1.0
        y[0:n, i], _, _ = sparse.complex_gen_solve_ilu(
            'RGMRES', nnz_az, az, irowz, icolz, ipivp,
            ipivq, istr, idiag, w, n,
            math.sqrt(machine.precision()), 500, y[0:n, i])

def sparse_matmul(k, nnza, a, irowa, icola, x, z, transa):
    """ Perform sparse matrix multiplcation with k^th matrix in  the pencil """
    n = np.size(x, 0)
    m0 = int(np.size(x, 1)/2)
    for i in range(m0):
        x[0:n, i] = sparse.complex_gen_matvec(
            transa, a[0:nnza[k], k], irowa[0:nnza[k], k],
            icola[0:nnza[k], k], z[0:n, i], 'N',
        )

[docs]def main(): """ Example for :func:`naginterfaces.library.sparseig.feast_poly_gen_solve`. Nonsymmetric Polynomial Eigenvalue Problem. >>> main() naginterfaces.library.sparseig.feast_poly_gen_solve Python Example Results. Nonsymmetric Polynomial Eigenvalue Problem. Eigenvalues: [-1.01154017+0.74243953j -0.97330836+0.60663851j] Right eigenvectors: [[-0.27867645-0.55398883j 0.64961648+0.07275759j] [ 0.15963493-0.05141476j -0.0367055 +0.19246955j] [ 0.20169124+0.24677364j -0.02640785+0.10024232j] [-0.022247 -0.02329904j 0.04061443-0.01888747j]] Left eigenvectors: [[-0.00184768-0.01019648j -0.03812357+0.02278326j] [ 0.01537005-0.00110981j -0.02825777-0.04867545j] [-0.7176863 -0.28399747j -0.5525527 +0.4415414j ] [-0.01783012+0.00584953j -0.01808489+0.04505064j]] """ print( 'naginterfaces.library.sparseig.feast_poly_gen_solve ' 'Python Example Results.' ) print('Nonsymmetric Polynomial Eigenvalue Problem.') # Get the input data for the problem deg, n, nnza, a, irowa, icola = input_data() # Initialize the FEAST data handle handle = sparseig.feast_init() # Set an option using the option setting routine sparseig.feast_option(handle, 'Max Iter = 50') # Get nodes and weights for the contour handle = contour(handle) # We need more arrays and variables before calling the solver irevcm = 0 ze = 0.0 + 0.0j m0 = n eps = 0.0 itera = 0 x = np.zeros((n, 2*m0), dtype=np.complex128) y = np.zeros((n, m0), dtype=np.complex128) z = np.zeros((n, 2*m0), dtype=np.complex128) d = np.zeros(m0, dtype=np.complex128) resid = np.zeros(2*m0, dtype=np.float64) # Call the reverse communication solver while True: irevcm, ze, k, m0, nconv, eps, itera = \ sparseig.feast_poly_gen_solve( handle, irevcm, deg, ze, x, y, m0, d, z, eps, itera, resid, ) if irevcm == 0: break if irevcm == 1: # Form the sparse matrix sum ze^i A_i az, irowz, icolz = form_matrix_pencil(ze, deg, n, nnza, a, irowa, icola, False) nnz_az = np.size(az) # Form incomplete LU factorization of sum ze^i A_i az, irowz, icolz, ipivp, ipivq, istr, idiag = \ incomplete_lu(az, irowz, icolz, n) if irevcm == 2: # Solve (sum ze^i A_i) y = w, with m0 righthand sides solve_lin_sys(nnz_az, az, irowz, icolz, ipivp, ipivq, istr, idiag, y) if irevcm == 3: # Form the sparse matrix (sum ze^i A_i)^H azh, irowzh, icolzh = form_matrix_pencil(ze, deg, n, nnza, a, irowa, icola, True) nnz_azh = np.size(azh) # Form incomplete LU factorization of (sum ze^i A_i)^H azh, irowzh, icolzh, ipivph, ipivqh, istrh, idiagh = \ incomplete_lu(azh, irowzh, icolzh, n) if irevcm == 4: # Solve (sum ze^i A_i)^H y = w, with m0 righthand sides solve_lin_sys(nnz_azh, azh, irowzh, icolzh, ipivph, ipivqh, istrh, idiagh, y) if irevcm == 5: # Compute x <- A_k z sparse_matmul(k, nnza, a, irowa, icola, x, z, 'N') if irevcm == 6: # Compute x <- A_k^H z sparse_matmul(k, nnza, a, irowa, icola, x, z, 'T') print("Eigenvalues:") print(d[0:nconv]) print("Right eigenvectors:") print(z[0:n, 0:nconv]) print("Left eigenvectors:") print(z[0:n, m0:m0+nconv])
if __name__ == '__main__': import doctest import sys sys.exit( doctest.testmod( None, verbose=True, report=False, optionflags=doctest.REPORT_NDIFF, ).failed )