295 lines
17 KiB
C
Executable file
295 lines
17 KiB
C
Executable file
/*****************************************************************************
|
|
* File : spgmr.h *
|
|
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
|
* Version of : 17 December 1999 *
|
|
*---------------------------------------------------------------------------*
|
|
* This is the header file for the implementation of SPGMR Krylov *
|
|
* iterative linear solver. The SPGMR algorithm is based on the Scaled *
|
|
* Preconditioned GMRES (Generalized Minimal Residual) method. *
|
|
* *
|
|
* The SPGMR algorithm solves a N by N linear system A x = b. *
|
|
* Preconditioning is allowed on the left, right, or both. *
|
|
* Scaling is allowed on both sides, and restarts are also allowed. *
|
|
* We denote the preconditioner and scaling matrices as follows: *
|
|
* P1 = left preconditioner *
|
|
* P2 = right preconditioner *
|
|
* S1 = diagonal matrix of scale factors for P1-inverse b *
|
|
* S2 = diagonal matrix of scale factors for P2 x *
|
|
* The matrices A, P1, and P2 are not required explicitly; only routines *
|
|
* that provide A, P1-inverse, and P2-inverse as operators are required. *
|
|
* *
|
|
* In this notation, SPGMR applies the underlying GMRES method to the *
|
|
* equivalent transformed system *
|
|
* Abar xbar = bbar , where *
|
|
* Abar = S1 (P1-inverse) A (P2-inverse) (S2-inverse) , *
|
|
* bbar = S1 (P1-inverse) b , and xbar = S2 P2 x . *
|
|
* *
|
|
* The scaling matrices must be chosen so that vectors S1 P1-inverse b *
|
|
* and S2 P2 x have dimensionless components. If preconditioning is done *
|
|
* on the left only (P2 = I), by a matrix P, then S2 must be a scaling *
|
|
* for x, while S1 is a scaling for P-inverse b, and so may also be taken *
|
|
* as a scaling for x. Similarly, if preconditioning is done on the *
|
|
* right only (P1 = I, P2 = P), then S1 must be a scaling for b, while S2 *
|
|
* is a scaling for P x, and may also be taken as a scaling for b. *
|
|
* *
|
|
* The stopping test for the SPGMR iterations is on the L2 norm of the *
|
|
* scaled preconditioned residual: *
|
|
* || bbar - Abar xbar ||_2 < delta *
|
|
* with an input test constant delta. *
|
|
* *
|
|
* The usage of this SPGMR solver involves supplying two routines and *
|
|
* making three calls. The user-supplied routines are *
|
|
* atimes (A_data, x, y) to compute the product y = A x, given x, *
|
|
* and *
|
|
* psolve (P_data, x, y, lr) to solve P1 x = y or P2 x = y for x, given y.*
|
|
* The three user calls are: *
|
|
* mem = SpgmrMalloc(N, lmax, machEnv); *
|
|
* to initialize memory, *
|
|
* flag = SpgmrSolve(mem,A_data,x,b,...,P_data,s1,s2,atimes,psolve,...); *
|
|
* to solve the system, and *
|
|
* SpgmrFree(mem); *
|
|
* to free the memory created by SpgmrMalloc. *
|
|
* Complete details for specifying atimes and psolve and for the usage calls *
|
|
* are given in the paragraphs below and in iterativ.h. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
#ifdef __cplusplus /* wrapper to enable C++ usage */
|
|
extern "C" {
|
|
#endif
|
|
|
|
#ifndef _spgmr_h
|
|
#define _spgmr_h
|
|
|
|
#include "llnltyps.h"
|
|
#include "iterativ.h"
|
|
#include "nvector.h"
|
|
|
|
|
|
/******************************************************************
|
|
* *
|
|
* Types: SpgmrMemRec, SpgmrMem *
|
|
*----------------------------------------------------------------*
|
|
* SpgmrMem is a pointer to an SpgmrMemRec which contains *
|
|
* the memory needed by SpgmrSolve. The SpgmrMalloc routine *
|
|
* returns a pointer of type SpgmrMem which should then be passed *
|
|
* in subsequent calls to SpgmrSolve. The SpgmrFree routine frees *
|
|
* the memory allocated by SpgmrMalloc. *
|
|
* *
|
|
* N is the linear system size. *
|
|
* *
|
|
* l_max is the maximum Krylov dimension that SpgmrSolve will be *
|
|
* permitted to use. *
|
|
* *
|
|
* V is the array of Krylov basis vectors v_1, ..., v_(l_max+1), *
|
|
* stored in V[0], ..., V[l_max], where l_max is the second *
|
|
* parameter to SpgmrMalloc. Each v_i is a length N vector of *
|
|
* type N_Vector. (N is the first parameter to SpgmrMalloc and *
|
|
* represents the size of the linear system.) *
|
|
* *
|
|
* Hes is the (l_max+1) x l_max Hessenberg matrix. It is stored *
|
|
* row-wise so that the (i,j)th element is given by Hes[i][j]. *
|
|
* *
|
|
* givens is a length 2*l_max array which represents the *
|
|
* Givens rotation matrices that arise in the algorithm. The *
|
|
* Givens rotation matrices F_0, F_1, ..., F_j, where F_i is *
|
|
* *
|
|
* 1 *
|
|
* 1 *
|
|
* c_i -s_i <--- row i *
|
|
* s_i c_i *
|
|
* 1 *
|
|
* 1 *
|
|
* *
|
|
* are represented in the givens vector as *
|
|
* givens[0]=c_0, givens[1]=s_0, givens[2]=c_1, givens[3]=s_1, *
|
|
* ..., givens[2j]=c_j, givens[2j+1]=s_j. *
|
|
* *
|
|
* xcor is a length N vector (type N_Vector) which holds the *
|
|
* scaled, preconditioned correction to the initial guess. *
|
|
* *
|
|
* yg is a length (l_max+1) array of reals used to hold "short" *
|
|
* vectors (e.g. y and g). *
|
|
* *
|
|
* vtemp is a length N vector (type N_Vector) used as temporary *
|
|
* vector storage during calculations. *
|
|
* *
|
|
******************************************************************/
|
|
|
|
typedef struct {
|
|
|
|
integer N;
|
|
int l_max;
|
|
|
|
N_Vector *V;
|
|
real **Hes;
|
|
real *givens;
|
|
N_Vector xcor;
|
|
real *yg;
|
|
N_Vector vtemp;
|
|
|
|
} SpgmrMemRec, *SpgmrMem;
|
|
|
|
|
|
/******************************************************************
|
|
* *
|
|
* Function : SpgmrMalloc *
|
|
*----------------------------------------------------------------*
|
|
* SpgmrMalloc allocates the memory used by SpgmrSolve. It *
|
|
* returns a pointer of type SpgmrMem which the user of the *
|
|
* SPGMR package should pass to SpgmrSolve. The parameter N *
|
|
* is the size of the system to be solved by SpgmrSolve and l_max *
|
|
* is the maximum Krylov dimension that SpgmrSolve will be *
|
|
* permitted to use. The parameter machEnv is a pointer to *
|
|
* machine environment-specific information. Pass NULL in the *
|
|
* ordinary sequential case (see nvector.h). This routine returns *
|
|
* NULL if there is a memory request failure. *
|
|
* *
|
|
******************************************************************/
|
|
|
|
SpgmrMem SpgmrMalloc(integer N, int l_max, void *machEnv);
|
|
|
|
|
|
/******************************************************************
|
|
* *
|
|
* Function : SpgmrSolve *
|
|
*----------------------------------------------------------------*
|
|
* SpgmrSolve solves the linear system Ax = b using the SPGMR *
|
|
* method. The return values are given by the symbolic constants *
|
|
* below. The first SpgmrSolve parameter is a pointer to memory *
|
|
* allocated by a prior call to SpgmrMalloc. The system size N *
|
|
* passed in the call to SpgmrMalloc should be the same as the *
|
|
* length of all N_Vector arguments passed to SpgmrSolve. *
|
|
* *
|
|
* mem is the pointer returned by SpgmrMalloc to the structure *
|
|
* containing the memory needed by SpgmrSolve. *
|
|
* *
|
|
* A_data is a pointer to information about the coefficient *
|
|
* matrix A. This pointer is passed to the user-supplied function *
|
|
* atimes. *
|
|
* *
|
|
* x is the initial guess x_0 upon entry and the solution *
|
|
* N_Vector upon exit with return value SPGMR_SUCCESS or *
|
|
* SPGMR_RES_REDUCED. For all other return values, the output x *
|
|
* is undefined. *
|
|
* *
|
|
* b is the right hand side N_Vector. It is undisturbed by this *
|
|
* function. *
|
|
* *
|
|
* pretype is the type of preconditioning to be used. Its *
|
|
* legal possible values are enumerated in iterativ.h. These *
|
|
* values are NONE=0, LEFT=1, RIGHT=2, and BOTH=3. *
|
|
* *
|
|
* gstype is the type of Gram-Schmidt orthogonalization to be *
|
|
* used. Its legal values are enumerated in iterativ.h. These *
|
|
* values are MODIFIED_GS=0 and CLASSICAL_GS=1. *
|
|
* *
|
|
* delta is the tolerance on the L2 norm of the scaled, *
|
|
* preconditioned residual. On return with value SPGMR_SUCCESS, *
|
|
* this residual satisfies || s1 P1_inv (b - Ax) ||_2 <= delta. *
|
|
* *
|
|
* max_restarts is the maximum number of times the algorithm is *
|
|
* allowed to restart. *
|
|
* *
|
|
* P_data is a pointer to preconditioner information. This *
|
|
* pointer is passed to the user-supplied function psolve. *
|
|
* *
|
|
* s1 is an N_Vector of positive scale factors for P1-inv b, where*
|
|
* P1 is the left preconditioner. (Not tested for positivity.) *
|
|
* Pass NULL if no scaling on P1-inv b is required. *
|
|
* *
|
|
* s2 is an N_Vector of positive scale factors for P2 x, where *
|
|
* P2 is the right preconditioner. (Not tested for positivity.) *
|
|
* Pass NULL if no scaling on P2 x is required. *
|
|
* *
|
|
* atimes is the user-supplied function which performs the *
|
|
* operation of multiplying A by a given vector. Its description *
|
|
* is given in iterativ.h. *
|
|
* *
|
|
* psolve is the user-supplied function which solves a *
|
|
* preconditioner system Pz = r, where P is P1 or P2. Its full *
|
|
* description is given in iterativ.h. The psolve function will *
|
|
* not be called if pretype is NONE; in that case, the user *
|
|
* should pass NULL for psolve. *
|
|
* *
|
|
* res_norm is a pointer to the L2 norm of the scaled, *
|
|
* preconditioned residual. On return with value SPGMR_SUCCESS or *
|
|
* SPGMR_RES_REDUCED, (*res_norm) contains the value *
|
|
* || s1 P1_inv (b - Ax) ||_2 for the computed solution x. *
|
|
* For all other return values, (*res_norm) is undefined. The *
|
|
* caller is responsible for allocating the memory (*res_norm) *
|
|
* to be filled in by SpgmrSolve. *
|
|
* *
|
|
* nli is a pointer to the number of linear iterations done in *
|
|
* the execution of SpgmrSolve. The caller is responsible for *
|
|
* allocating the memory (*nli) to be filled in by SpgmrSolve. *
|
|
* *
|
|
* nps is a pointer to the number of calls made to psolve during *
|
|
* the execution of SpgmrSolve. The caller is responsible for *
|
|
* allocating the memory (*nps) to be filled in by SpgmrSolve. *
|
|
* *
|
|
* Note.. Repeated calls can be made to SpgmrSolve with varying *
|
|
* input arguments. If, however, the problem size N or the *
|
|
* maximum Krylov dimension l_max changes, then a call to *
|
|
* SpgmrMalloc must be made to obtain new memory for SpgmrSolve *
|
|
* to use. *
|
|
* *
|
|
******************************************************************/
|
|
|
|
|
|
int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b,
|
|
int pretype, int gstype, real delta, int max_restarts,
|
|
void *P_data, N_Vector s1, N_Vector s2, ATimesFn atimes,
|
|
PSolveFn psolve, real *res_norm, int *nli, int *nps);
|
|
|
|
|
|
/* Return values for SpgmrSolve */
|
|
|
|
#define SPGMR_SUCCESS 0 /* Converged */
|
|
#define SPGMR_RES_REDUCED 1 /* Did not converge, but reduced
|
|
norm of residual */
|
|
#define SPGMR_CONV_FAIL 2 /* Failed to converge */
|
|
#define SPGMR_QRFACT_FAIL 3 /* QRfact found singular matrix */
|
|
#define SPGMR_PSOLVE_FAIL_REC 4 /* psolve failed recoverably */
|
|
#define SPGMR_MEM_NULL -1 /* mem argument is NULL */
|
|
#define SPGMR_ATIMES_FAIL -2 /* atimes returned failure flag */
|
|
#define SPGMR_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */
|
|
#define SPGMR_GS_FAIL -4 /* Gram-Schmidt routine
|
|
returned failure flag */
|
|
#define SPGMR_QRSOL_FAIL -5 /* QRsol found singular R */
|
|
|
|
|
|
/******************************************************************
|
|
* *
|
|
* Function : SpgmrFree *
|
|
*----------------------------------------------------------------*
|
|
* SpgmrMalloc frees the memory allocated by SpgmrMalloc. It is *
|
|
* illegal to use the pointer mem after a call to SpgmrFree. *
|
|
* *
|
|
******************************************************************/
|
|
|
|
void SpgmrFree(SpgmrMem mem);
|
|
|
|
|
|
/******************************************************************
|
|
* Macro: SPGMR_VTEMP *
|
|
* *
|
|
*----------------------------------------------------------------*
|
|
* This macro provides access to the work vector vtemp in the *
|
|
* memory block of the SPGMR module. The argument mem is the *
|
|
* memory pointer returned by SpgmrMalloc, of type SpgmrMem, *
|
|
* and the macro value is of type N_Vector. *
|
|
* On a return from SpgmrSolve with *nli = 0, this vector *
|
|
* contains the scaled preconditioned initial residual, *
|
|
* s1 * P1_inverse * (b - A x_0). *
|
|
******************************************************************/
|
|
|
|
#define SPGMR_VTEMP(mem) (mem->vtemp)
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|