GALAHAD PSLS package#

purpose#

Given a sparse symmetric matrix \(A = \{ a_{ij} \}_{n \times n}\), the psls package builds a suitable symmetric, positive definite—or diagonally dominant—preconditioner \(P\) of \(A\) or a symmetric sub-matrix thereof. The matrix \(A\) need not be definite. Facilities are provided to apply the preconditioner to a given vector, and to remove rows and columns (symmetrically) from the initial preconditioner without a full re-factorization.

method#

The basic preconditioners are described in detail in

A. R. Conn, N. I. M. Gould and Ph. L. Toint, LANCELOT. A fortran package for large-scale nonlinear optimization (release A). Springer Verlag Series in Computational Mathematics 17, Berlin (1992), Section 3.3.10,

along with the more modern versions implements in ICFS due to

C.-J. Lin and J. J. More’, ``Incomplete Cholesky factorizations with limited memory’’. SIAM Journal on Scientific Computing 21 (1999) 21-45,

and in HSL_MI28 described by

J. A. Scott and M. Tuma, ``HSL_MI28: an efficient and robust limited-memory incomplete Cholesky factorization code’’. ACM Transactions on Mathematical Software 40(4) (2014), Article 24.

The factorization methods used by the package sls in conjunction with some preconditioners are described in the documentation to that package. The key features of the external solvers supported by sls are given in the following table.

External solver characteristics#

solver

factorization

indefinite \(A\)

out-of-core

parallelised

SILS/MA27

multifrontal

yes

no

no

HSL_MA57

multifrontal

yes

no

no

HSL_MA77

multifrontal

yes

yes

OpenMP core

HSL_MA86

left-looking

yes

no

OpenMP fully

HSL_MA87

left-looking

no

no

OpenMP fully

HSL_MA97

multifrontal

yes

no

OpenMP core

SSIDS

multifrontal

yes

no

CUDA core

MUMPS

multifrontal

yes

optionally

MPI

PARDISO

left-right-looking

yes

no

OpenMP fully

MKL_PARDISO

left-right-looking

yes

optionally

OpenMP fully

PaStix

left-right-looking

yes

no

OpenMP fully

WSMP

left-right-looking

yes

no

OpenMP fully

POTR

dense

no

no

with parallel LAPACK

SYTR

dense

yes

no

with parallel LAPACK

PBTR

dense band

no

no

with parallel LAPACK

Note that, with the exception of SSIDS and the Netlib reference LAPACK codes, the solvers themselves do not form part of this package and must be obtained/linked to separately. See the documentation for sls for more details and references. Dummy instances are provided for solvers that are unavailable. Also note that additional flexibility may be obtained by calling the solvers directly rather that via this package.

Orderings to reduce the bandwidth, as implemented in HSL’s MC61, are due to

J. K. Reid and J. A. Scott, ``Ordering symmetric sparse matrices for small profile and wavefront’’. International Journal for Numerical Methods in Engineering 45 (1999) 1737-1755.

If a subset of the rows and columns are specified, the remaining rows/columns are removed before processing. Any subsequent removal of rows and columns is achieved using the Schur-complement updating package scu unless a complete re-factorization is likely more efficient.

matrix storage#

The symmetric \(n\) by \(n\) matrix \(A\) may be presented and stored in a variety of formats. But crucially symmetry is exploited by only storing values from the lower triangular part (i.e, those entries that lie on or below the leading diagonal).

Dense storage format: The matrix \(A\) is stored as a compact dense matrix by rows, that is, the values of the entries of each row in turn are stored in order within an appropriate real one-dimensional array. Since \(A\) is symmetric, only the lower triangular part (that is the part \(A_{ij}\) for \(0 \leq j \leq i \leq n-1\)) need be held. In this case the lower triangle should be stored by rows, that is component \(i * i / 2 + j\) of the storage array A_val will hold the value \(A_{ij}\) (and, by symmetry, \(A_{ji}\)) for \(0 \leq j \leq i \leq n-1\). The string A_type = ‘dense’ should be specified.

Sparse co-ordinate storage format: Only the nonzero entries of the matrices are stored. For the \(l\)-th entry, \(0 \leq l \leq ne-1\), of \(A\), its row index i, column index j and value \(A_{ij}\), \(0 \leq j \leq i \leq n-1\), are stored as the \(l\)-th components of the integer arrays A_row and A_col and real array A_val, respectively, while the number of nonzeros is recorded as A_ne = \(ne\). Note that only the entries in the lower triangle should be stored. The string A_type = ‘coordinate’ should be specified.

Sparse row-wise storage format: Again only the nonzero entries are stored, but this time they are ordered so that those in row i appear directly before those in row i+1. For the i-th row of \(A\) the i-th component of the integer array A_ptr holds the position of the first entry in this row, while A_ptr(n) holds the total number of entries. The column indices j, \(0 \leq j \leq i\), and values \(A_{ij}\) of the entries in the i-th row are stored in components l = A_ptr(i), …, A_ptr(i+1)-1 of the integer array A_col, and real array A_val, respectively. Note that as before only the entries in the lower triangle should be stored. For sparse matrices, this scheme almost always requires less storage than its predecessor. The string A_type = ‘sparse_by_rows’ should be specified.

Diagonal storage format: If \(A\) is diagonal (i.e., \(A_{ij} = 0\) for all \(0 \leq i \neq j \leq n-1\)) only the diagonals entries \(A_{ii}\), \(0 \leq i \leq n-1\) need be stored, and the first n components of the array A_val may be used for the purpose. The string A_type = ‘diagonal’ should be specified.

Multiples of the identity storage format: If \(A\) is a multiple of the identity matrix, (i.e., \(H = \alpha I\) where \(I\) is the n by n identity matrix and \(\alpha\) is a scalar), it suffices to store \(\alpha\) as the first component of A_val. The string A_type = ‘scaled_identity’ should be specified.

The identity matrix format: If \(A\) is the identity matrix, no values need be stored. The string A_type = ‘identity’ should be specified.

The zero matrix format: The same is true if \(A\) is the zero matrix, but now the string A_type = ‘zero’ or ‘none’ should be specified.

introduction to function calls#

To solve a given problem, functions from the psls package must be called in the following order:

See the examples section for illustrations of use.

callable functions#

overview of functions provided#

// namespaces

namespace conf;

// typedefs

typedef float spc_;
typedef double rpc_;
typedef int ipc_;

// structs

struct psls_control_type;
struct psls_inform_type;
struct psls_time_type;

// global functions

void psls_initialize(
    void **data,
    struct psls_control_type* control,
    ipc_ *status
);

void psls_read_specfile(
    struct psls_control_type* control,
    const char specfile[]
);

void psls_import(
    struct psls_control_type* control,
    void **data,
    ipc_ *status,
    ipc_ n,
    const char type[],
    ipc_ ne,
    const ipc_ row[],
    const ipc_ col[],
    const ipc_ ptr[]
);

void psls_reset_control(
    struct psls_control_type* control,
    void **data,
    ipc_ *status
);

void psls_form_preconditioner(
    void **data,
    ipc_ *status,
    ipc_ ne,
    const rpc_ val[]
);

void psls_form_subset_preconditioner(
    void **data,
    ipc_ *status,
    ipc_ ne,
    const rpc_ val[],
    ipc_ n_sub,
    const ipc_ sub[]
);

void psls_update_preconditioner(
    void **data,
    ipc_ *status,
    ipc_ ne,
    const rpc_ val[],
    ipc_ n_del,
    const ipc_ del[]
);

void psls_apply_preconditioner(void **data, ipc_ *status, ipc_ n, rpc_ sol[]);
void psls_information(void **data, struct psls_inform_type* inform, ipc_ *status);

void psls_terminate(
    void **data,
    struct psls_control_type* control,
    struct psls_inform_type* inform
);

typedefs#

typedef float spc_

spc_ is real single precision

typedef double rpc_

rpc_ is the real working precision used, but may be changed to float by defining the preprocessor variable SINGLE.

typedef int ipc_

ipc_ is the default integer word length used, but may be changed to int64_t by defining the preprocessor variable INTEGER_64.

function calls#

void psls_initialize(
    void **data,
    struct psls_control_type* control,
    ipc_ *status
)

Set default control values and initialize private data

Parameters:

data

holds private internal data

control

is a struct containing control information (see psls_control_type)

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are (currently):

  • 0

    The initialization was successful.

void psls_read_specfile(
    struct psls_control_type* control,
    const char specfile[]
)

Read the content of a specification file, and assign values associated with given keywords to the corresponding control parameters. An in-depth discussion of specification files is available, and a detailed list of keywords with associated default values is provided in $GALAHAD/src/psls/PSLS.template. See also Table 2.1 in the Fortran documentation provided in $GALAHAD/doc/psls.pdf for a list of how these keywords relate to the components of the control structure.

Parameters:

control

is a struct containing control information (see psls_control_type)

specfile

is a character string containing the name of the specification file

void psls_import(
    struct psls_control_type* control,
    void **data,
    ipc_ *status,
    ipc_ n,
    const char type[],
    ipc_ ne,
    const ipc_ row[],
    const ipc_ col[],
    const ipc_ ptr[]
)

Import structural matrix data into internal storage prior to solution.

Parameters:

control

is a struct whose members provide control paramters for the remaining prcedures (see psls_control_type)

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are:

  • 1

    The import was successful, and the package is ready for the solve phase

  • -1

    An allocation error occurred. A message indicating the offending array is written on unit control.error, and the returned allocation status and a string containing the name of the offending array are held in inform.alloc_status and inform.bad_alloc respectively.

  • -2

    A deallocation error occurred. A message indicating the offending array is written on unit control.error and the returned allocation status and a string containing the name of the offending array are held in inform.alloc_status and inform.bad_alloc respectively.

  • -3

    The restriction n > 0 or requirement that type contains its relevant string ‘dense’, ‘coordinate’, ‘sparse_by_rows’ or ‘diagonal’ has been violated.

n

is a scalar variable of type ipc_, that holds the number of rows in the symmetric matrix \(A\).

type

is a one-dimensional array of type char that specifies the symmetric storage scheme used for the matrix \(A\). It should be one of ‘coordinate’, ‘sparse_by_rows’ or ‘dense’; lower or upper case variants are allowed.

ne

is a scalar variable of type ipc_, that holds the number of entries in the lower triangular part of \(A\) in the sparse co-ordinate storage scheme. It need not be set for any of the other schemes.

row

is a one-dimensional array of size ne and type ipc_, that holds the row indices of the lower triangular part of \(A\) in the sparse co-ordinate storage scheme. It need not be set for any of the other three schemes, and in this case can be NULL.

col

is a one-dimensional array of size ne and type ipc_, that holds the column indices of the lower triangular part of \(A\) in either the sparse co-ordinate, or the sparse row-wise storage scheme. It need not be set when the dense storage scheme is used, and in this case can be NULL.

ptr

is a one-dimensional array of size n+1 and type ipc_, that holds the starting position of each row of the lower triangular part of \(A\), as well as the total number of entries, in the sparse row-wise storage scheme. It need not be set when the other schemes are used, and in this case can be NULL.

void psls_reset_control(
    struct psls_control_type* control,
    void **data,
    ipc_ *status
)

Reset control parameters after import if required.

Parameters:

control

is a struct whose members provide control paramters for the remaining prcedures (see psls_control_type)

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are:

  • 1

    The import was successful, and the package is ready for the solve phase

void psls_form_preconditioner(
    void **data,
    ipc_ *status,
    ipc_ ne,
    const rpc_ val[]
)

Form and factorize a preconditioner \(P\) of the matrix \(A\).

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package.

Possible values are:

  • 0

    The factors were generated successfully.

  • -1

    An allocation error occurred. A message indicating the offending array is written on unit control.error, and the returned allocation status and a string containing the name of the offending array are held in inform.alloc_status and inform.bad_alloc respectively.

  • -2

    A deallocation error occurred. A message indicating the offending array is written on unit control.error and the returned allocation status and a string containing the name of the offending array are held in inform.alloc_status and inform.bad_alloc respectively.

  • -26

    The requested solver is not available.

  • -29

    This option is not available with this solver.

ne

is a scalar variable of type ipc_, that holds the number of entries in the lower triangular part of the symmetric matrix \(A\).

val

is a one-dimensional array of size ne and type rpc_, that holds the values of the entries of the lower triangular part of the symmetric matrix \(A\) in any of the supported storage schemes.

void psls_form_subset_preconditioner(
    void **data,
    ipc_ *status,
    ipc_ ne,
    const rpc_ val[],
    ipc_ n_sub,
    const ipc_ sub[]
)

Form and factorize a \(P\) preconditioner of a symmetric submatrix of the matrix \(A\).

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package.

Possible values are:

  • 0

    The factors were generated successfully.

  • -1

    An allocation error occurred. A message indicating the offending array is written on unit control.error, and the returned allocation status and a string containing the name of the offending array are held in inform.alloc_status and inform.bad_alloc respectively.

  • -2

    A deallocation error occurred. A message indicating the offending array is written on unit control.error and the returned allocation status and a string containing the name of the offending array are held in inform.alloc_status and inform.bad_alloc respectively.

  • -26

    The requested solver is not available.

  • -29

    This option is not available with this solver.

ne

is a scalar variable of type ipc_, that holds the number of entries in the lower triangular part of the symmetric matrix \(A\).

val

is a one-dimensional array of size ne and type rpc_, that holds the values of the entries of the lower triangular part of the symmetric matrix \(A\) in any of the supported storage schemes.

n_sub

is a scalar variable of type ipc_, that holds the number of rows (and columns) of the required submatrix of \(A\).

sub

is a one-dimensional array of size n_sub and type ipc_, that holds the indices of the rows of required submatrix.

void psls_update_preconditioner(
    void **data,
    ipc_ *status,
    ipc_ ne,
    const rpc_ val[],
    ipc_ n_del,
    const ipc_ del[]
)

Update the preconditioner \(P\) when rows (amd columns) are removed.

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package.

Possible values are:

  • 0

    The factors were generated successfully.

  • -1

    An allocation error occurred. A message indicating the offending array is written on unit control.error, and the returned allocation status and a string containing the name of the offending array are held in inform.alloc_status and inform.bad_alloc respectively.

  • -2

    A deallocation error occurred. A message indicating the offending array is written on unit control.error and the returned allocation status and a string containing the name of the offending array are held in inform.alloc_status and inform.bad_alloc respectively.

  • -26

    The requested solver is not available.

  • -29

    This option is not available with this solver.

ne

is a scalar variable of type ipc_, that holds the number of entries in the lower triangular part of the symmetric matrix \(A\).

val

is a one-dimensional array of size ne and type rpc_, that holds the values of the entries of the lower triangular part of the symmetric matrix \(A\) in any of the supported storage schemes.

n_del

is a scalar variable of type ipc_, that holds the number of rows (and columns) of (sub) matrix that are to be deleted.

del

is a one-dimensional array of size n_fix and type ipc_, that holds the indices of the rows that are to be deleted.

void psls_apply_preconditioner(void **data, ipc_ *status, ipc_ n, rpc_ sol[])

Solve the linear system \(Px=b\).

Parameters:

data

holds private internal data

status

is a scalar variable of type ipc_, that gives the exit status from the package.

Possible values are:

  • 0

    The required solution was obtained.

  • -1

    An allocation error occurred. A message indicating the offending array is written on unit control.error, and the returned allocation status and a string containing the name of the offending array are held in inform.alloc_status and inform.bad_alloc respectively.

  • -2

    A deallocation error occurred. A message indicating the offending array is written on unit control.error and the returned allocation status and a string containing the name of the offending array are held in inform.alloc_status and inform.bad_alloc respectively.

n

is a scalar variable of type ipc_, that holds the number of entries in the vectors \(b\) and \(x\).

sol

is a one-dimensional array of size n and type double. On entry, it must hold the vector \(b\). On a successful exit, its contains the solution \(x\). Any component corresponding to rows/columns not in the initial subset recorded by psls_form_subset_preconditioner, or in those subsequently deleted by psls_update_preconditioner, will not be altered.

void psls_information(void **data, struct psls_inform_type* inform, ipc_ *status)

Provide output information

Parameters:

data

holds private internal data

inform

is a struct containing output information (see psls_inform_type)

status

is a scalar variable of type ipc_, that gives the exit status from the package. Possible values are (currently):

  • 0

    The values were recorded successfully

void psls_terminate(
    void **data,
    struct psls_control_type* control,
    struct psls_inform_type* inform
)

Deallocate all internal private storage

Parameters:

data

holds private internal data

control

is a struct containing control information (see psls_control_type)

inform

is a struct containing output information (see psls_inform_type)

available structures#

psls_control_type structure#

#include <galahad_psls.h>

struct psls_control_type {
    // fields

    bool f_indexing;
    ipc_ error;
    ipc_ out;
    ipc_ print_level;
    ipc_ preconditioner;
    ipc_ semi_bandwidth;
    ipc_ scaling;
    ipc_ ordering;
    ipc_ max_col;
    ipc_ icfs_vectors;
    ipc_ mi28_lsize;
    ipc_ mi28_rsize;
    rpc_ min_diagonal;
    bool new_structure;
    bool get_semi_bandwidth;
    bool get_norm_residual;
    bool space_critical;
    bool deallocate_error_fatal;
    char definite_linear_solver[31];
    char prefix[31];
    struct sls_control_type sls_control;
    struct mi28_control mi28_control;
};

detailed documentation#

control derived type as a C struct

components#

bool f_indexing

use C or Fortran sparse matrix indexing

ipc_ error

unit for error messages

ipc_ out

unit for monitor output

ipc_ print_level

controls level of diagnostic output

ipc_ preconditioner

which preconditioner to use:

  • <0 no preconditioning occurs, \(P = I\)

  • 0 the preconditioner is chosen automatically (forthcoming, and currently defaults to 1).

  • 1 \(A\) is replaced by the diagonal, \(P\) = diag( max(\(A\), .min_diagonal ) ).

  • 2 \(A\) is replaced by the band \(P\) = band(\(A\)) with semi-bandwidth .semi_bandwidth.

  • 3 \(A\) is replaced by the reordered band \(P\) = band( order(\(A\)) ) with semi-bandwidth .semi_bandwidth, where order is chosen by the HSL package MC61 to move entries closer to the diagonal.

  • 4 \(P\) is a full factorization of \(A\) using Schnabel-Eskow modifications, in which small or negative diagonals are made sensibly positive during the factorization.

  • 5 \(P\) is a full factorization of \(A\) due to Gill, Murray, Ponceleon and Saunders, in which an indefinite factorization is altered to give a positive definite one.

  • 6 \(P\) is an incomplete Cholesky factorization of \(A\) using the package ICFS due to Lin and More’.

  • 7 \(P\) is an incomplete factorization of \(A\) implemented as HSL_MI28 from HSL.

  • 8 \(P\) is an incomplete factorization of \(A\) due to Munskgaard (forthcoming).

  • >8 treated as 0.

N.B. Options 3-8 may require additional external software that is not part of the package, and that must be obtained separately.

ipc_ semi_bandwidth

the semi-bandwidth for band(H) when .preconditioner = 2,3

ipc_ scaling

not used at present

ipc_ ordering

see scaling

ipc_ max_col

maximum number of nonzeros in a column of \(A\) for Schur-complement factorization to accommodate newly deleted rpws and columns

ipc_ icfs_vectors

number of extra vectors of length n required by the Lin-More’ incomplete Cholesky preconditioner when .preconditioner = 6

ipc_ mi28_lsize

the maximum number of fill entries within each column of the incomplete factor L computed by HSL_MI28 when .preconditioner = 7. In general, increasing mi28_lsize improve the quality of the preconditioner but increases the time to compute and then apply the preconditioner. Values less than 0 are treated as 0

ipc_ mi28_rsize

the maximum number of entries within each column of the strictly lower triangular matrix \(R\) used in the computation of the preconditioner by HSL_MI28 when .preconditioner = 7. Rank-1 arrays of size .mi28_rsize \* n are allocated internally to hold \(R\). Thus the amount of memory used, as well as the amount of work involved in computing the preconditioner, depends on mi28_rsize. Setting mi28_rsize > 0 generally leads to a higher quality preconditioner than using mi28_rsize = 0, and choosing mi28_rsize >= mi28_lsize is generally recommended

rpc_ min_diagonal

the minimum permitted diagonal in diag(max(H,.min_diagonal))

bool new_structure

set new_structure true if the storage structure for the input matrix has changed, and false if only the values have changed

bool get_semi_bandwidth

set get_semi_bandwidth true if the semi-bandwidth of the submatrix is to be calculated

bool get_norm_residual

set get_norm_residual true if the residual when applying the preconditioner are to be calculated

bool space_critical

if space is critical, ensure allocated arrays are no bigger than needed

bool deallocate_error_fatal

exit if any deallocation fails

char definite_linear_solver[31]

the name of the definite linear equation solver used. Possible choices are currently: ‘sils’, ‘ma27’, ‘ma57’, ‘ma77’, ‘ma86’, ‘ma87’, ‘ma97’, ‘ssids’, ‘mumps’, ‘pardiso’, ‘mkl_pardiso’, ‘pastix’, ‘wsmp’, ‘potr’, ‘sytr’ and ‘pbtr’, although only ‘potr’, ‘sytr’, ‘pbtr’ and, for OMP 4.0-compliant compilers, ‘ssids’ are installed by default; others are easily installed (see README.external). More details of the capabilities of each solver are provided in the documentation for galahad_sls.

char prefix[31]

all output lines will be prefixed by prefix(2:LEN(TRIM(.prefix))-1) where prefix contains the required string enclosed in quotes, e.g. “string” or ‘string’

struct sls_control_type sls_control

control parameters for SLS

struct mi28_control mi28_control

control parameters for HSL_MI28

psls_time_type structure#

#include <galahad_psls.h>

struct psls_time_type {
    // fields

    spc_ total;
    spc_ assemble;
    spc_ analyse;
    spc_ factorize;
    spc_ solve;
    spc_ update;
    rpc_ clock_total;
    rpc_ clock_assemble;
    rpc_ clock_analyse;
    rpc_ clock_factorize;
    rpc_ clock_solve;
    rpc_ clock_update;
};

detailed documentation#

time derived type as a C struct

components#

spc_ total

total time

spc_ assemble

time to assemble the preconditioner prior to factorization

spc_ analyse

time for the analysis phase

spc_ factorize

time for the factorization phase

spc_ solve

time for the linear solution phase

spc_ update

time to update the factorization

rpc_ clock_total

total clock time spent in the package

rpc_ clock_assemble

clock time to assemble the preconditioner prior to factorization

rpc_ clock_analyse

clock time for the analysis phase

rpc_ clock_factorize

clock time for the factorization phase

rpc_ clock_solve

clock time for the linear solution phase

rpc_ clock_update

clock time to update the factorization

psls_inform_type structure#

#include <galahad_psls.h>

struct psls_inform_type {
    // fields

    ipc_ status;
    ipc_ alloc_status;
    ipc_ analyse_status;
    ipc_ factorize_status;
    ipc_ solve_status;
    int64_t factorization_integer;
    int64_t factorization_real;
    ipc_ preconditioner;
    ipc_ semi_bandwidth;
    ipc_ reordered_semi_bandwidth;
    ipc_ out_of_range;
    ipc_ duplicates;
    ipc_ upper;
    ipc_ missing_diagonals;
    ipc_ semi_bandwidth_used;
    ipc_ neg1;
    ipc_ neg2;
    bool perturbed;
    rpc_ fill_in_ratio;
    rpc_ norm_residual;
    char bad_alloc[81];
    ipc_ mc61_info[10];
    rpc_ mc61_rinfo[15];
    struct psls_time_type time;
    struct sls_inform_type sls_inform;
    struct mi28_info mi28_info;
};

detailed documentation#

inform derived type as a C struct

components#

ipc_ status

reported return status:

  • 0

    success

  • -1

    allocation error

  • -2

    deallocation error

  • -3

    matrix data faulty (.n < 1, .ne < 0)

ipc_ alloc_status

STAT value after allocate failure.

ipc_ analyse_status

status return from factorization

ipc_ factorize_status

status return from factorization

ipc_ solve_status

status return from solution phase

int64_t factorization_integer

number of integer words to hold factors

int64_t factorization_real

number of real words to hold factors

ipc_ preconditioner

code for the actual preconditioner used (see control.preconditioner)

ipc_ semi_bandwidth

the actual semi-bandwidth

ipc_ reordered_semi_bandwidth

the semi-bandwidth following reordering (if any)

ipc_ out_of_range

number of indices out-of-range

ipc_ duplicates

number of duplicates

ipc_ upper

number of entries from the strict upper triangle

ipc_ missing_diagonals

number of missing diagonal entries for an allegedly-definite matrix

ipc_ semi_bandwidth_used

the semi-bandwidth used

ipc_ neg1

number of 1 by 1 pivots in the factorization

ipc_ neg2

number of 2 by 2 pivots in the factorization

bool perturbed

has the preconditioner been perturbed during the fctorization?

rpc_ fill_in_ratio

ratio of fill in to original nonzeros

rpc_ norm_residual

the norm of the solution residual

char bad_alloc[81]

name of array which provoked an allocate failure

ipc_ mc61_info[10]

the integer and real output arrays from mc61

rpc_ mc61_rinfo[15]

see mc61_info

struct psls_time_type time

times for various stages

struct sls_inform_type sls_inform

inform values from SLS

struct mi28_info mi28_info

the output info structure from HSL’s mi28

example calls#

This is an example of how to use the package to solve a definite linear system; the code is available in $GALAHAD/src/psls/C/pslst.c . A variety of supported matrix storage formats are shown.

Notice that C-style indexing is used, and that this is flagged by setting control.f_indexing to false. The floating-point type rpc_ is set in galahad_precision.h to double by default, but to float if the preprocessor variable SINGLE is defined. Similarly, the integer type ipc_ from galahad_precision.h is set to int by default, but to int64_t if the preprocessor variable INTEGER_64 is defined.

/* pslst.c */
/* Full test for the PSLS C interface using C sparse matrix indexing */

#include <stdio.h>
#include <math.h>
#include <string.h>
#include "galahad_precision.h"
#include "galahad_cfunctions.h"
#include "galahad_psls.h"

int main(void) {

    // Derived types
    void *data;
    struct psls_control_type control;
    struct psls_inform_type inform;

    // Set problem data
    ipc_ n = 5; // dimension of A
    ipc_ ne = 7; // number of elements of A
    ipc_ dense_ne = n * ( n + 1 ) / 2; // number of elements of dense A

    ipc_ row[] = {0, 1, 1, 2, 2, 3, 4}; // A indices & values, NB lower triangle
    ipc_ col[] = {0, 0, 4, 1, 2, 2, 4};
    ipc_ ptr[] = {0, 1, 3, 5, 6, 7};
    rpc_ val[] = {2.0, 3.0, 6.0, 4.0, 1.0, 5.0, 1.0};
    rpc_ dense[] = {2.0, 3.0, 0.0, 0.0, 4.0, 1.0, 0.0,
                      0.0, 5.0, 0.0, 0.0, 6.0, 0.0, 0.0, 1.0};
    char st = ' ';
    ipc_ status;
    ipc_ status_apply;

    printf(" C sparse matrix indexing\n\n");

    printf(" basic tests of storage formats\n\n");

    for( ipc_ d=1; d <= 3; d++){

        // Initialize PSLS
        psls_initialize( &data, &control, &status );
        control.preconditioner = 2; // band preconditioner
        control.semi_bandwidth = 1; // semibandwidth
        strcpy( control.definite_linear_solver, "sils" );

        // Set user-defined control options
        control.f_indexing = false; // C sparse matrix indexing

        switch(d){
            case 1: // sparse co-ordinate storage
                st = 'C';
                psls_import( &control, &data, &status, n,
                             "coordinate", ne, row, col, NULL );
                psls_form_preconditioner( &data, &status, ne, val );
                break;
            printf(" case %1" i_ipc_ " break\n",d);
            case 2: // sparse by rows
                st = 'R';
                psls_import( &control, &data, &status, n,
                             "sparse_by_rows", ne, NULL, col, ptr );
                psls_form_preconditioner( &data, &status, ne, val );
                break;
            case 3: // dense
                st = 'D';
                psls_import( &control, &data, &status, n,
                             "dense", ne, NULL, NULL, NULL );
                psls_form_preconditioner( &data, &status, dense_ne, dense );
                break;
            }

        // Set right-hand side b in x
        rpc_ x[] = {8.0, 45.0, 31.0, 15.0, 17.0};   // values

        if(status == 0){
          psls_information( &data, &inform, &status );
          psls_apply_preconditioner( &data, &status_apply, n, x );
        }else{
          status_apply = - 1;
        }

        printf("%c storage: status from form & factorize = %" i_ipc_
               " apply = %" i_ipc_ "\n", st, status, status_apply );

        //printf("x: ");
        //for( ipc_ i = 0; i < n; i++) printf("%f ", x[i]);

        // Delete internal workspace
        psls_terminate( &data, &control, &inform );
    }
}

This is the same example, but now fortran-style indexing is used; the code is available in $GALAHAD/src/psls/C/pslstf.c .

/* pslstf.c */
/* Full test for the PSLS C interface using Fortran sparse matrix indexing */

#include <stdio.h>
#include <math.h>
#include <string.h>
#include "galahad_precision.h"
#include "galahad_cfunctions.h"
#include "galahad_psls.h"

int main(void) {

    // Derived types
    void *data;
    struct psls_control_type control;
    struct psls_inform_type inform;

    // Set problem data
    ipc_ n = 5; // dimension of A
    ipc_ ne = 7; // number of elements of A
    ipc_ dense_ne = n * ( n + 1 ) / 2; // number of elements of dense A

    ipc_ row[] = {1, 2, 2, 3, 3, 4, 5}; // A indices & values, NB lower triangle
    ipc_ col[] = {1, 1, 5, 2, 3, 3, 5};
    ipc_ ptr[] = {1, 2, 4, 6, 7, 8};
    rpc_ val[] = {2.0, 3.0, 6.0, 4.0, 1.0, 5.0, 1.0};
    rpc_ dense[] = {2.0, 3.0, 0.0, 0.0, 4.0, 1.0, 0.0,
                      0.0, 5.0, 0.0, 0.0, 6.0, 0.0, 0.0, 1.0};
    char st = ' ';
    ipc_ status;
    ipc_ status_apply;

    printf(" Fortran sparse matrix indexing\n\n");

    printf(" basic tests of storage formats\n\n");

    for( ipc_ d=1; d <= 3; d++){

        // Initialize PSLS
        psls_initialize( &data, &control, &status );
        control.preconditioner = 2; // band preconditioner
        control.semi_bandwidth = 1; // semibandwidth
        strcpy( control.definite_linear_solver, "sils" );

        // Set user-defined control options
        control.f_indexing = true; // fortran sparse matrix indexing

        switch(d){
            case 1: // sparse co-ordinate storage
                st = 'C';
                psls_import( &control, &data, &status, n,
                             "coordinate", ne, row, col, NULL );
                psls_form_preconditioner( &data, &status, ne, val );
                break;
            printf(" case %1" i_ipc_ " break\n",d);
            case 2: // sparse by rows
                st = 'R';
                psls_import( &control, &data, &status, n,
                             "sparse_by_rows", ne, NULL, col, ptr );
                psls_form_preconditioner( &data, &status, ne, val );
                break;
            case 3: // dense
                st = 'D';
                psls_import( &control, &data, &status, n,
                             "dense", ne, NULL, NULL, NULL );
                psls_form_preconditioner( &data, &status, dense_ne, dense );
                break;
            }

        // Set right-hand side b in x
        rpc_ x[] = {8.0, 45.0, 31.0, 15.0, 17.0};   // values

        if(status == 0){
          psls_information( &data, &inform, &status );
          psls_apply_preconditioner( &data, &status_apply, n, x );
        }else{
          status_apply = - 1;
        }

        printf("%c storage: status from form & factorize = %" i_ipc_
               " apply = %" i_ipc_ "\n", st, status, status_apply );

        //printf("x: ");
        //for( ipc_ i = 0; i < n; i++) printf("%f ", x[i]);

        // Delete internal workspace
        psls_terminate( &data, &control, &inform );
    }
}