Remove old version of CVODE
We now use the current version from the Sundials git submodule
This commit is contained in:
parent
b4a1fb2db1
commit
4e551f69ab
25 changed files with 0 additions and 10843 deletions
|
|
@ -1,609 +0,0 @@
|
|||
|
||||
/******************************************************************
|
||||
* *
|
||||
* File : band.h *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 5 May 1998 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the header file for a generic BAND linear solver *
|
||||
* package. There are two sets of band solver routines listed in *
|
||||
* this file: one set uses type BandMat defined below and the *
|
||||
* other set uses the type real ** for band matrix arguments. *
|
||||
* The two sets of band solver routines make it easy to work *
|
||||
* with two types of band matrices: *
|
||||
* *
|
||||
* (1) The BandMat type is intended for use with large *
|
||||
* band matrices whose elements/columns may be stored in *
|
||||
* non-contiguous memory locations or even distributed into *
|
||||
* different processor memories. This type may be modified to *
|
||||
* include such distribution information. If this is done, *
|
||||
* then all the routines that use BandMat must be modified to *
|
||||
* reflect the new data structure. *
|
||||
* *
|
||||
* (2) The set of routines that use real ** (and NOT the BandMat *
|
||||
* type) is intended for use with small matrices which can *
|
||||
* easily be allocated within a contiguous block of memory *
|
||||
* on a single processor. *
|
||||
* *
|
||||
* Routines that work with the type BandMat begin with "Band". *
|
||||
* The BandAllocMat function allocates a band matrix for use in *
|
||||
* the other matrix routines listed in this file. Matrix storage *
|
||||
* details are given in the documentation for the type BandMat. *
|
||||
* The BandAllocPiv function allocates memory for pivot *
|
||||
* information. The storage allocated by BandAllocMat and *
|
||||
* BandAllocPiv is deallocated by the routines BandFreeMat and *
|
||||
* BandFreePiv, respectively. The BandFactor and BandBacksolve *
|
||||
* routines perform the actual solution of a band linear system. *
|
||||
* Note that the BandBacksolve routine has a parameter b of type *
|
||||
* N_Vector. The current implementation makes use of a machine *
|
||||
* environment specific macro (N_VDATA) which may not exist for *
|
||||
* other implementations of the type N_Vector. Thus, the *
|
||||
* implementation of BandBacksolve may need to change if the *
|
||||
* type N_Vector is changed. *
|
||||
* *
|
||||
* Routines that work with real ** begin with "band" (except for *
|
||||
* the factor and solve routines which are called gbfa and gbsl, *
|
||||
* respectively). The underlying matrix storage is described in *
|
||||
* the documentation for bandalloc. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#ifdef __cplusplus /* wrapper to enable C++ usage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _band_h
|
||||
#define _band_h
|
||||
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Type: BandMat *
|
||||
*----------------------------------------------------------------*
|
||||
* The type BandMat is the type of a large (possibly distributed) *
|
||||
* band matrix. It is defined to be a pointer to a structure *
|
||||
* with the following fields: *
|
||||
* *
|
||||
* size is the number of columns (== number of rows) *
|
||||
* *
|
||||
* mu is the upper bandwidth, 0 <= mu <= size-1 *
|
||||
* *
|
||||
* ml is the lower bandwidth, 0 <= ml <= size-1 *
|
||||
* *
|
||||
* smu is the storage upper bandwidth, mu <= smu <= size-1. *
|
||||
* The BandFactor routine writes the LU factors *
|
||||
* into the storage for A. The upper triangular factor U, *
|
||||
* however, may have an upper bandwidth as big as *
|
||||
* MIN(size-1,mu+ml) because of partial pivoting. The smu *
|
||||
* field holds the upper bandwidth allocated for A. *
|
||||
* *
|
||||
* data is a two dimensional array used for component storage. *
|
||||
* The elements of a band matrix of type BandMat are *
|
||||
* stored columnwise (i.e. columns are stored one on top *
|
||||
* of the other in memory). Only elements within the *
|
||||
* specified bandwidths are stored. *
|
||||
* *
|
||||
* If we number rows and columns in the band matrix starting *
|
||||
* from 0, then *
|
||||
* *
|
||||
* data[0] is a pointer to (smu+ml+1)*size contiguous locations *
|
||||
* which hold the elements within the band of A *
|
||||
* *
|
||||
* data[j] is a pointer to the uppermost element within the band *
|
||||
* in the jth column. This pointer may be treated as *
|
||||
* an array indexed from smu-mu (to access the *
|
||||
* uppermost element within the band in the jth *
|
||||
* column) to smu+ml (to access the lowest element *
|
||||
* within the band in the jth column). (Indices from 0 *
|
||||
* to smu-mu-1 give access to extra storage elements *
|
||||
* required by BandFactor.) *
|
||||
* *
|
||||
* data[j][i-j+smu] is the (i,j)th element, j-mu <= i <= j+ml. *
|
||||
* *
|
||||
* The macros below allow a user to access individual matrix *
|
||||
* elements without writing out explicit data structure *
|
||||
* references and without knowing too much about the underlying *
|
||||
* element storage. The only storage assumption needed is that *
|
||||
* elements are stored columnwise and that a pointer into the jth *
|
||||
* column of elements can be obtained via the BAND_COL macro. The *
|
||||
* BAND_COL_ELEM macro selects an element from a column which has *
|
||||
* already been isolated via BAND_COL. BAND_COL_ELEM allows the *
|
||||
* user to avoid the translation from the matrix location (i,j) *
|
||||
* to the index in the array returned by BAND_COL at which the *
|
||||
* (i,j)th element is stored. See the documentation for BAND_COL *
|
||||
* and BAND_COL_ELEM for usage details. Users should use these *
|
||||
* macros whenever possible. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
typedef struct {
|
||||
integer size;
|
||||
integer mu, ml, smu;
|
||||
real **data;
|
||||
} *BandMat;
|
||||
|
||||
|
||||
/* BandMat accessor macros */
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Macro : BAND_ELEM *
|
||||
* Usage : BAND_ELEM(A,i,j) = a_ij; OR *
|
||||
* a_ij = BAND_ELEM(A,i,j); *
|
||||
*----------------------------------------------------------------*
|
||||
* BAND_ELEM(A,i,j) references the (i,j)th element of the *
|
||||
* N by N band matrix A, where 0 <= i,j <= N-1. The location *
|
||||
* (i,j) should further satisfy j-(A->mu) <= i <= j+(A->ml). *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#define BAND_ELEM(A,i,j) ((A->data)[j][i-j+(A->smu)])
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Macro : BAND_COL *
|
||||
* Usage : col_j = BAND_COL(A,j); *
|
||||
*----------------------------------------------------------------*
|
||||
* BAND_COL(A,j) references the diagonal element of the jth *
|
||||
* column of the N by N band matrix A, 0 <= j <= N-1. The type of *
|
||||
* the expression BAND_COL(A,j) is real *. The pointer returned *
|
||||
* by the call BAND_COL(A,j) can be treated as an array which is *
|
||||
* indexed from -(A->mu) to (A->ml). *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#define BAND_COL(A,j) (((A->data)[j])+(A->smu))
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Macro : BAND_COL_ELEM *
|
||||
* Usage : col_j = BAND_COL(A,j); *
|
||||
* BAND_COL_ELEM(col_j,i,j) = a_ij; OR *
|
||||
* a_ij = BAND_COL_ELEM(col_j,i,j); *
|
||||
*----------------------------------------------------------------*
|
||||
* This macro references the (i,j)th entry of the band matrix A *
|
||||
* when used in conjunction with BAND_COL as shown above. The *
|
||||
* index (i,j) should satisfy j-(A->mu) <= i <= j+(A->ml). *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#define BAND_COL_ELEM(col_j,i,j) (col_j[i-j])
|
||||
|
||||
|
||||
/* Functions that use the BandMat representation for a band matrix */
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : BandAllocMat *
|
||||
* Usage : A = BandAllocMat(N, mu, ml, smu); *
|
||||
* if (A == NULL) ... memory request failed *
|
||||
*----------------------------------------------------------------*
|
||||
* BandAllocMat allocates memory for an N by N band matrix with *
|
||||
* upper bandwidth mu, lower bandwidth ml, and storage upper *
|
||||
* bandwidth smu. Pass smu as follows depending on whether A will *
|
||||
* be factored by BandFactor: *
|
||||
* *
|
||||
* (1) Pass smu = mu if A will not be factored. *
|
||||
* *
|
||||
* (2) Pass smu = MIN(N-1,mu+ml) if A will be factored. *
|
||||
* *
|
||||
* BandAllocMat returns the storage allocated (type BandMat) or *
|
||||
* NULL if the request for matrix storage cannot be satisfied. *
|
||||
* See the documentation for the type BandMat for matrix storage *
|
||||
* details. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
BandMat BandAllocMat(integer N, integer mu, integer ml, integer smu);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : BandAllocPiv *
|
||||
* Usage : p = BandAllocPiv(N); *
|
||||
* if (p == NULL) ... memory request failed *
|
||||
*----------------------------------------------------------------*
|
||||
* BandAllocPiv allocates memory for pivot information to be *
|
||||
* filled in by the BandFactor routine during the factorization *
|
||||
* of an N by N band matrix. The underlying type for pivot *
|
||||
* information is an array of N integers and this routine returns *
|
||||
* the pointer to the memory it allocates. If the request for *
|
||||
* pivot storage cannot be satisfied, BandAllocPiv returns NULL. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
integer *BandAllocPiv(integer N);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : BandFactor *
|
||||
* Usage : ier = BandFactor(A, p); *
|
||||
* if (ier != 0) ... A is singular *
|
||||
*----------------------------------------------------------------*
|
||||
* BandFactor performs the LU factorization of the N by N band *
|
||||
* matrix A. This is done using standard Gaussian elimination *
|
||||
* with partial pivoting. *
|
||||
* *
|
||||
* A successful LU factorization leaves the "matrix" A and the *
|
||||
* pivot array p with the following information: *
|
||||
* *
|
||||
* (1) p[k] contains the row number of the pivot element chosen *
|
||||
* at the beginning of elimination step k, k=0, 1, ..., N-1. *
|
||||
* *
|
||||
* (2) If the unique LU factorization of A is given by PA = LU, *
|
||||
* where P is a permutation matrix, L is a lower triangular *
|
||||
* matrix with all 1's on the diagonal, and U is an upper *
|
||||
* triangular matrix, then the upper triangular part of A *
|
||||
* (including its diagonal) contains U and the strictly lower *
|
||||
* triangular part of A contains the multipliers, I-L. *
|
||||
* *
|
||||
* BandFactor returns 0 if successful. Otherwise it encountered *
|
||||
* a zero diagonal element during the factorization. In this case *
|
||||
* it returns the column index (numbered from one) at which *
|
||||
* it encountered the zero. *
|
||||
* *
|
||||
* Important Note: A must be allocated to accommodate the increase*
|
||||
* in upper bandwidth that occurs during factorization. If, *
|
||||
* mathematically, A is a band matrix with upper bandwidth mu and *
|
||||
* lower bandwidth ml, then the upper triangular factor U can *
|
||||
* have upper bandwidth as big as smu=MIN(n-1,mu+ml). The lower *
|
||||
* triangular factor L has lower bandwidth ml. Allocate A with *
|
||||
* call A = BandAllocMat(N,mu,ml,smu), where mu, ml, and smu are *
|
||||
* as defined above. The user does not have to zero the "extra" *
|
||||
* storage allocated for the purpose of factorization. This will *
|
||||
* handled by the BandFactor routine. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
integer BandFactor(BandMat A, integer *p);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : BandBacksolve *
|
||||
* Usage : BandBacksolve(A, p, b); *
|
||||
*----------------------------------------------------------------*
|
||||
* BandBacksolve solves the N-dimensional system A x = b using *
|
||||
* the LU factorization in A and the pivot information in p *
|
||||
* computed in BandFactor. The solution x is returned in b. This *
|
||||
* routine cannot fail if the corresponding call to BandFactor *
|
||||
* did not fail. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void BandBacksolve(BandMat A, integer *p, N_Vector b);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : BandZero *
|
||||
* Usage : BandZero(A); *
|
||||
*----------------------------------------------------------------*
|
||||
* A(i,j) <- 0.0, j-(A->mu) <= i <= j+(A->ml). *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void BandZero(BandMat A);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : BandCopy *
|
||||
* Usage : BandCopy(A, B, copymu, copyml); *
|
||||
*----------------------------------------------------------------*
|
||||
* BandCopy copies the submatrix with upper and lower bandwidths *
|
||||
* copymu, copyml of the N by N band matrix A into the N by N *
|
||||
* band matrix B. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void BandCopy(BandMat A, BandMat B, integer copymu, integer copyml);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function: BandScale *
|
||||
* Usage : BandScale(c, A); *
|
||||
*----------------------------------------------------------------*
|
||||
* A(i,j) <- c*A(i,j), j-(A->mu) <= i <= j+(A->ml). *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void BandScale(real c, BandMat A);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : BandAddI *
|
||||
* Usage : BandAddI(A); *
|
||||
*----------------------------------------------------------------*
|
||||
* A(j,j) <- A(j,j)+1.0, 0 <= j <= (A->size)-1. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void BandAddI(BandMat A);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : BandFreeMat *
|
||||
* Usage : BandFreeMat(A); *
|
||||
*----------------------------------------------------------------*
|
||||
* BandFreeMat frees the memory allocated by BandAllocMat for *
|
||||
* the band matrix A. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void BandFreeMat(BandMat A);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : BandFreePiv *
|
||||
* Usage : BandFreePiv(p); *
|
||||
*----------------------------------------------------------------*
|
||||
* BandFreePiv frees the memory allocated by BandAllocPiv for *
|
||||
* the pivot information array p. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void BandFreePiv(integer *p);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : BandPrint *
|
||||
* Usage : BandPrint(A); *
|
||||
*----------------------------------------------------------------*
|
||||
* This routine prints the N by N band matrix A (upper and lower *
|
||||
* bandwidths A->mu and A->ml, respectively) to standard output *
|
||||
* as it would normally appear on paper. It is intended as a *
|
||||
* debugging tool with small values of N. The elements are *
|
||||
* printed using the %g option. A blank line is printed before *
|
||||
* and after the matrix. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void BandPrint(BandMat A);
|
||||
|
||||
|
||||
|
||||
/* Functions that use the real ** representation for a band matrix */
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : bandalloc *
|
||||
* Usage : real **a; *
|
||||
* a = bandalloc(n, smu, ml); *
|
||||
* if (a == NULL) ... memory request failed *
|
||||
*----------------------------------------------------------------*
|
||||
* bandalloc(n, smu, ml) allocates storage for an n by n band *
|
||||
* matrix A with storage upper bandwidth smu and lower bandwidth *
|
||||
* ml. It returns a pointer to the newly allocated storage if *
|
||||
* successful. If the memory request cannot be satisfied, then *
|
||||
* bandalloc returns NULL. If, mathematically, A has upper and *
|
||||
* lower bandwidths mu and ml, respectively, then the value *
|
||||
* passed to bandalloc for smu may need to be greater than mu. *
|
||||
* The gbfa routine writes the LU factors into the storage (named *
|
||||
* "a" in the above usage documentation) for A (thus destroying *
|
||||
* the original elements of A). The upper triangular factor U, *
|
||||
* however, may have a larger upper bandwidth than the upper *
|
||||
* bandwidth mu of A. Thus some "extra" storage for A must be *
|
||||
* allocated if A is to be factored by gbfa. Pass smu as follows: *
|
||||
* *
|
||||
* (1) Pass smu = mu if A will not be factored. *
|
||||
* *
|
||||
* (2) Pass smu = MIN(n-1,mu+ml) if A will be factored. *
|
||||
* *
|
||||
* The underlying type of the band matrix returned is real **. If *
|
||||
* we allocate a band matrix A in real **a by *
|
||||
* a = bandalloc(n,smu,ml), then a[0] is a pointer to *
|
||||
* n * (smu + ml + 1) contiguous storage locations and a[j] is a *
|
||||
* pointer to the uppermost element in the storage for the jth *
|
||||
* column. The expression a[j][i-j+smu] references the (i,j)th *
|
||||
* element of A, where 0 <= i,j <= n-1 and j-mu <= i <= j+ml. *
|
||||
* (The elements a[j][0], a[j][1], ..., a[j][smu-mu-1] are used *
|
||||
* by gbfa and gbsl.) *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
real **bandalloc(integer n, integer smu, integer ml);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : bandallocpiv *
|
||||
* Usage : integer *pivot; *
|
||||
* pivot = bandallocpiv(n); *
|
||||
* if (pivot == NULL) ... memory request failed *
|
||||
*----------------------------------------------------------------*
|
||||
* bandallocpiv(n) allocates an array of n integers. It returns a *
|
||||
* pointer to the first element in the array if successful. It *
|
||||
* returns NULL if the memory request could not be satisfied. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
integer *bandallocpiv(integer n);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : gbfa *
|
||||
* Usage : integer ier; *
|
||||
* ier = gbfa(a,n,mu,ml,smu,p); *
|
||||
* if (ier > 0) ... zero element encountered during *
|
||||
* the factorization *
|
||||
*----------------------------------------------------------------*
|
||||
* gbfa(a,n,mu,ml,smu,p) factors the n by n band matrix A (upper *
|
||||
* and lower bandwidths mu and ml, storage upper bandwidth smu) *
|
||||
* stored in "a". It overwrites the elements of A with the LU *
|
||||
* factors and it keeps track of the pivot rows chosen in the *
|
||||
* pivot array p. *
|
||||
* *
|
||||
* A successful LU factorization leaves a and pivot array p with *
|
||||
* the following information: *
|
||||
* *
|
||||
* (1) p[k] contains the row number of the pivot element chosen *
|
||||
* at the beginning of elimination step k, k=0, 1, ..., n-1. *
|
||||
* *
|
||||
* (2) If the unique LU factorization of A is given by PA = LU, *
|
||||
* where P is a permutation matrix, L is a lower triangular *
|
||||
* matrix with all 1's on the diagonal, and U is an upper *
|
||||
* triangular matrix, then the upper triangular part of A *
|
||||
* (including its diagonal) contains U and the strictly lower *
|
||||
* triangular part of A contains the multipliers, I-L. *
|
||||
* *
|
||||
* gbfa returns 0 if successful. Otherwise it encountered a zero *
|
||||
* diagonal element during the factorization. In this case it *
|
||||
* returns the column index (numbered from one) at which it *
|
||||
* encountered the zero. *
|
||||
* *
|
||||
* IMPORTANT NOTE: Suppose A is a band matrix with upper *
|
||||
* bandwidth mu and lower bandwidth ml, then the upper triangular *
|
||||
* factor U can have upper bandwidth as big as MIN(n-1,mu+ml) *
|
||||
* because of partial pivoting. The lower triangular factor L has *
|
||||
* lower bandwidth ml. Thus, if A is to be factored and *
|
||||
* backsolved using gbfa and gbsl, then it should be allocated *
|
||||
* as a = bandalloc(n,smu,ml), where smu = MIN(n-1,mu+ml). The *
|
||||
* call to gbfa is ier = gbfa(a,n,mu,ml,smu,p). The corresponding *
|
||||
* call to gbsl is gbsl(a,n,smu,ml,p,b). The user does not need *
|
||||
* to zero the "extra" storage allocated for the purpose of *
|
||||
* factorization. This is handled by the gbfa routine. If A is *
|
||||
* not going to be factored and backsolved, then it can be *
|
||||
* allocated as a = bandalloc(n,smu,ml). In either case, all *
|
||||
* routines in this section use the parameter name smu for a *
|
||||
* parameter which must be the "storage upper bandwidth" which *
|
||||
* was passed to bandalloc. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
integer gbfa(real **a, integer n, integer mu, integer ml, integer smu,
|
||||
integer *p);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : gbsl *
|
||||
* Usage : real *b; *
|
||||
* ier = gbfa(a,n,mu,ml,smu,p); *
|
||||
* if (ier == 0) gbsl(a,n,smu,ml,p,b); *
|
||||
*----------------------------------------------------------------*
|
||||
* gbsl(a,n,smu,ml,p,b) solves the n by n linear system *
|
||||
* Ax = b, where A is band matrix stored in "a" with storage *
|
||||
* upper bandwidth smu and lower bandwidth ml. It assumes that A *
|
||||
* has been LU factored and the pivot array p has been set by a *
|
||||
* successful call gbfa(a,n,mu,ml,smu,p). The solution x is *
|
||||
* written into the b array. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void gbsl(real **a, integer n, integer smu, integer ml, integer *p, real *b);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : bandzero *
|
||||
* Usage : bandzero(a,n,mu,ml,smu); *
|
||||
*----------------------------------------------------------------*
|
||||
* a(i,j) <- 0.0, 0 <= i,j <= n-1, j-mu <= i <= j+ml. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void bandzero(real **a, integer n, integer mu, integer ml, integer smu);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : bandcopy *
|
||||
* Usage : bandcopy(a,b,n,a_smu,b_smu,copymu,copyml); *
|
||||
*----------------------------------------------------------------*
|
||||
* b(i,j) <- a(i,j), 0 <= i,j <= n-1, j-copymu <= i <= j+copyml. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void bandcopy(real **a, real **b, integer n, integer a_smu, integer b_smu,
|
||||
integer copymu, integer copyml);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : bandscale *
|
||||
* Usage : bandscale(c,a,n,mu,ml); *
|
||||
*----------------------------------------------------------------*
|
||||
* a(i,j) <- c*a(i,j), 0 <= i,j <= n-1, j-mu <= i <= j+ml. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void bandscale(real c, real **a, integer n, integer mu, integer ml,
|
||||
integer smu);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : bandaddI *
|
||||
* Usage : bandaddI(a,n,smu); *
|
||||
*----------------------------------------------------------------*
|
||||
* a(j,j) <- a(j,j)+1.0, 0 <= j <= n-1. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void bandaddI(real **a, integer n, integer smu);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : bandfreepiv *
|
||||
* Usage : bandfreepiv(p); *
|
||||
*----------------------------------------------------------------*
|
||||
* bandfreepiv(p) frees the pivot array p allocated by *
|
||||
* bandallocpiv. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void bandfreepiv(integer *p);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : bandfree *
|
||||
* Usage : bandfree(a); *
|
||||
*----------------------------------------------------------------*
|
||||
* bandfree(a) frees the band matrix a allocated by bandalloc. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void bandfree(real **a);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : bandprint *
|
||||
* Usage : bandprint(a,n,mu,ml,smu); *
|
||||
*----------------------------------------------------------------*
|
||||
* bandprint(a,n,mu,ml,smu) prints the n by n band matrix stored *
|
||||
* in a (with upper bandwidth mu and lower bandwidth ml) to *
|
||||
* standard output as it would normally appear on paper. It is *
|
||||
* intended as a debugging tool with small values of n. The *
|
||||
* elements are printed using the %g option. A blank line is *
|
||||
* printed before and after the matrix. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void bandprint(real **a, integer n, integer mu, integer ml, integer smu);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,221 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : cvband.h *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 24 February 2000 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the header file for the CVODE band linear solver, *
|
||||
* CVBAND. *
|
||||
* *
|
||||
* Note: The type integer must be large enough to store the value *
|
||||
* N + mupper + mlower, where N is the linear system size and *
|
||||
* mupper and mlower are the upper and lower bandwidths, *
|
||||
* respectively, passed to CVBand. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#ifdef __cplusplus /* wrapper to enable C++ usage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _cvband_h
|
||||
#define _cvband_h
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cvode.h"
|
||||
#include "llnltyps.h"
|
||||
#include "band.h"
|
||||
#include "nvector.h"
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* CVBAND solver statistics indices *
|
||||
*----------------------------------------------------------------*
|
||||
* The following enumeration gives a symbolic name to each *
|
||||
* CVBAND statistic. The symbolic names are used as indices into *
|
||||
* the iopt and ropt arrays passed to CVodeMalloc. *
|
||||
* The CVBAND statistics are: *
|
||||
* *
|
||||
* iopt[BAND_NJE] : number of Jacobian evaluations, i.e. of *
|
||||
* calls made to the band Jacobian routine *
|
||||
* (default or user-supplied). *
|
||||
* *
|
||||
* iopt[BAND_LRW] : size (in real words) of real workspace *
|
||||
* matrices and vectors used by this solver. *
|
||||
* *
|
||||
* iopt[BAND_LIW] : size (in integer words) of integer *
|
||||
* workspace vectors used by this solver. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
enum { BAND_NJE=CVODE_IOPT_SIZE, BAND_LRW, BAND_LIW };
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* CVBAND solver constants *
|
||||
*----------------------------------------------------------------*
|
||||
* CVB_MSBJ : maximum number of steps between band Jacobian *
|
||||
* evaluations *
|
||||
* *
|
||||
* CVB_DGMAX : maximum change in gamma between band Jacobian *
|
||||
* evaluations *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#define CVB_MSBJ 50
|
||||
|
||||
#define CVB_DGMAX RCONST(0.2)
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Type : CVBandJacFn *
|
||||
*----------------------------------------------------------------*
|
||||
* A band Jacobian approximation function Jac must have the *
|
||||
* prototype given below. Its parameters are: *
|
||||
* *
|
||||
* N is the length of all vector arguments. *
|
||||
* *
|
||||
* mupper is the upper half-bandwidth of the approximate banded *
|
||||
* Jacobian. This parameter is the same as the mupper parameter *
|
||||
* passed by the user to the CVBand function. *
|
||||
* *
|
||||
* mlower is the lower half-bandwidth of the approximate banded *
|
||||
* Jacobian. This parameter is the same as the mlower parameter *
|
||||
* passed by the user to the CVBand function. *
|
||||
* *
|
||||
* J is the band matrix (of type BandMat) that will be loaded *
|
||||
* by a CVBandJacFn with an approximation to the Jacobian matrix *
|
||||
* J = (df_i/dy_j) at the point (t,y). *
|
||||
* J is preset to zero, so only the nonzero elements need to be *
|
||||
* loaded. Three efficient ways to load J are: *
|
||||
* *
|
||||
* (1) (with macros - no explicit data structure references) *
|
||||
* for (j=0; j < N; j++) { *
|
||||
* col_j = BAND_COL(J,j); *
|
||||
* for (i=j-mupper; i <= j+mlower; i++) { *
|
||||
* generate J_ij = the (i,j)th Jacobian element *
|
||||
* BAND_COL_ELEM(col_j,i,j) = J_ij; *
|
||||
* } *
|
||||
* } *
|
||||
* *
|
||||
* (2) (with BAND_COL macro, but without BAND_COL_ELEM macro) *
|
||||
* for (j=0; j < N; j++) { *
|
||||
* col_j = BAND_COL(J,j); *
|
||||
* for (k=-mupper; k <= mlower; k++) { *
|
||||
* generate J_ij = the (i,j)th Jacobian element, i=j+k *
|
||||
* col_j[k] = J_ij; *
|
||||
* } *
|
||||
* } *
|
||||
* *
|
||||
* (3) (without macros - explicit data structure references) *
|
||||
* offset = J->smu; *
|
||||
* for (j=0; j < N; j++) { *
|
||||
* col_j = ((J->data)[j])+offset; *
|
||||
* for (k=-mupper; k <= mlower; k++) { *
|
||||
* generate J_ij = the (i,j)th Jacobian element, i=j+k *
|
||||
* col_j[k] = J_ij; *
|
||||
* } *
|
||||
* } *
|
||||
* Caution: J->smu is generally NOT the same as mupper. *
|
||||
* *
|
||||
* The BAND_ELEM(A,i,j) macro is appropriate for use in small *
|
||||
* problems in which efficiency of access is NOT a major concern. *
|
||||
* *
|
||||
* f is the right hand side function for the ODE problem. *
|
||||
* *
|
||||
* f_data is a pointer to user data to be passed to f, the same *
|
||||
* as the F_data parameter passed to CVodeMalloc. *
|
||||
* *
|
||||
* t is the current value of the independent variable. *
|
||||
* *
|
||||
* y is the current value of the dependent variable vector, *
|
||||
* namely the predicted value of y(t). *
|
||||
* *
|
||||
* fy is the vector f(t,y). *
|
||||
* *
|
||||
* ewt is the error weight vector. *
|
||||
* *
|
||||
* h is a tentative step size in t. *
|
||||
* *
|
||||
* uround is the machine unit roundoff. *
|
||||
* *
|
||||
* jac_data is a pointer to user data - the same as the jac_data *
|
||||
* parameter passed to CVBand. *
|
||||
* *
|
||||
* nfePtr is a pointer to the memory location containing the *
|
||||
* CVODE problem data nfe = number of calls to f. The Jacobian *
|
||||
* routine should update this counter by adding on the number *
|
||||
* of f calls made in order to approximate the Jacobian, if any. *
|
||||
* For example, if the routine calls f a total of N times, then *
|
||||
* the update is *nfePtr += N. *
|
||||
* *
|
||||
* vtemp1, vtemp2, and vtemp3 are pointers to memory allocated *
|
||||
* for vectors of length N which can be used by a CVBandJacFn *
|
||||
* as temporary storage or work space. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
typedef void (*CVBandJacFn)(integer N, integer mupper, integer mlower,
|
||||
BandMat J, RhsFn f, void *f_data, real t,
|
||||
N_Vector y, N_Vector fy, N_Vector ewt, real h,
|
||||
real uround, void *jac_data, long int *nfePtr,
|
||||
N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : CVBand *
|
||||
*----------------------------------------------------------------*
|
||||
* A call to the CVBand function links the main CVODE integrator *
|
||||
* with the CVBAND linear solver. *
|
||||
* *
|
||||
* cvode_mem is the pointer to CVODE memory returned by *
|
||||
* CVodeMalloc. *
|
||||
* *
|
||||
* mupper is the upper bandwidth of the band Jacobian *
|
||||
* approximation. *
|
||||
* *
|
||||
* mlower is the lower bandwidth of the band Jacobian *
|
||||
* approximation. *
|
||||
* *
|
||||
* *
|
||||
* bjac is the band Jacobian approximation routine to be used. *
|
||||
* A user-supplied bjac routine must be of type *
|
||||
* CVBandJacFn. Pass NULL for bjac to use the default *
|
||||
* difference quotient routine CVBandDQJac supplied *
|
||||
* with this solver. *
|
||||
* *
|
||||
* jac_data is a pointer to user data which is passed to the *
|
||||
* bjac routine every time it is called. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void CVBand(void *cvode_mem, integer mupper, integer mlower, CVBandJacFn bjac,
|
||||
void *jac_data);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : CVBandDQJac *
|
||||
*----------------------------------------------------------------*
|
||||
* This routine generates a banded difference quotient *
|
||||
* approximation to the Jacobian of f(t,y). *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void CVBandDQJac(integer N, integer mupper, integer mlower, BandMat J,
|
||||
RhsFn f, void *f_data, real t, N_Vector y, N_Vector fy,
|
||||
N_Vector ewt, real h, real uround, void *jac_data,
|
||||
long int *nfePtr, N_Vector vtemp1, N_Vector vtemp2,
|
||||
N_Vector vtemp3);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : cvbandpre.h *
|
||||
* Programmers : Michael Wittman and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 23 March 2000 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the header file for the CVBANDPRE module, which *
|
||||
* provides a banded difference quotient Jacobian-based *
|
||||
* preconditioner and solver routines for use with CVSPGMR. *
|
||||
* *
|
||||
* Summary: *
|
||||
* These routines provide a band matrix preconditioner based on *
|
||||
* difference quotients of the ODE right-hand side function f. *
|
||||
* The user supplies parameters *
|
||||
* mu = upper half-bandwidth (number of super-diagonals) *
|
||||
* ml = lower half-bandwidth (number of sub-diagonals) *
|
||||
* The routines generate a band matrix of bandwidth ml + mu + 1 *
|
||||
* and use this to form a preconditioner for use with the Krylov *
|
||||
* linear solver in CVSPGMR. Although this matrix is intended *
|
||||
* to approximate the Jacobian df/dy, it may be a very crude *
|
||||
* approximation. The true Jacobian need not be banded, or its *
|
||||
* true bandwith may be larger than ml + mu + 1, as long as the *
|
||||
* banded approximation generated here is sufficiently accurate *
|
||||
* to speed convergence as a preconditioner. *
|
||||
* *
|
||||
* Usage: *
|
||||
* The following is a summary of the usage of this module. *
|
||||
* Details of the calls to CVodeMalloc, CVSpgmr, and CVode are *
|
||||
* available in the CVODE User Guide. *
|
||||
* To use these routines, the sequence of calls in the user *
|
||||
* main program should be as follows: *
|
||||
* *
|
||||
* CVBandPreData bp_data; *
|
||||
* ... *
|
||||
* bp_data = CVBandPreAlloc(N, f, f_data, mu, ml); *
|
||||
* ... *
|
||||
* cvode_mem = CVodeMalloc(...); *
|
||||
* ... *
|
||||
* CVSpgmr(cvode_mem, pretype, gstype, maxl, delt, *
|
||||
* CVBandPrecond, CVBandPSolve, bp_data); *
|
||||
* ... *
|
||||
* flag = CVode(...); *
|
||||
* ... *
|
||||
* CVBandPreFree(bp_data); *
|
||||
* ... *
|
||||
* CVodeFree(cvode_mem); *
|
||||
* *
|
||||
* Notes: *
|
||||
* (1) Include this file for the CVBandPreData type definition. *
|
||||
* (2) In the CVBandPreAlloc call, the arguments N, f, and f_data *
|
||||
* are the same as in the call to CVodeMalloc. *
|
||||
* (3) In the CVSpgmr call, the user is free to specify the inputs*
|
||||
* pretype and gstype, and the optional inputs maxl and delt. *
|
||||
* But the last three arguments must be as shown, with the *
|
||||
* last argument being the pointer returned by CVBandPreAlloc.*
|
||||
* (4) The CVBandPrecond and CVBandPSolve functions are never *
|
||||
* called by the user explicitly; they are simply passed to *
|
||||
* the CVSpgmr function. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
#ifdef __cplusplus /* wrapper to enable C++ usage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _cvbandpre_h
|
||||
#define _cvbandpre_h
|
||||
|
||||
#include "cvode.h"
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
#include "band.h"
|
||||
|
||||
|
||||
/************* CVBandPreData type definition ************/
|
||||
|
||||
typedef struct {
|
||||
/* Data set by user in CVBandPreAlloc: */
|
||||
RhsFn f;
|
||||
void *f_data;
|
||||
integer ml, mu;
|
||||
|
||||
/* Data set by CVBandPrecond: */
|
||||
BandMat savedJ;
|
||||
BandMat savedP;
|
||||
integer *pivots;
|
||||
} *CVBandPreData;
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : CVBandPreAlloc *
|
||||
*----------------------------------------------------------------*
|
||||
* CVBandPreAlloc allocates and initializes a CVBandPreData *
|
||||
* structure to be passed to CVSpgmr (and subsequently used by *
|
||||
* CVBandPrecond and CVBandPSolve). *
|
||||
* *
|
||||
* The parameters of CVBandPreAlloc are as follows: *
|
||||
* *
|
||||
* N is the length of all vector arguments. *
|
||||
* *
|
||||
* f is the right hand side function. *
|
||||
* *
|
||||
* f_data is a pointer to the optional extra data for f. *
|
||||
* *
|
||||
* mu is the upper half bandwidth. *
|
||||
* *
|
||||
* ml is the lower half bandwidth. *
|
||||
* *
|
||||
* CVBandPreAlloc returns the storage pointer (type CVBandPreData)*
|
||||
* or NULL if the request for storage cannot be satisfied. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
CVBandPreData CVBandPreAlloc(integer N, RhsFn f, void *f_data,
|
||||
integer mu, integer ml);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : CVBandPreFree *
|
||||
*----------------------------------------------------------------*
|
||||
* CVBandPreFree frees the memory allocated by CVBandPreAlloc in *
|
||||
* the argument pdata. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void CVBandPreFree(CVBandPreData pdata);
|
||||
|
||||
|
||||
|
||||
/* Prototypes of CVBandPrecond and CVBandPSolve */
|
||||
|
||||
|
||||
int CVBandPrecond(integer N, real t, N_Vector y, N_Vector fy, boole jok,
|
||||
boole *jcurPtr, real gamma, N_Vector ewt, real h,
|
||||
real uround, long int *nfePtr, void *bp_data,
|
||||
N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
|
||||
|
||||
|
||||
int CVBandPSolve(integer N, real t, N_Vector y, N_Vector fy, N_Vector vtemp,
|
||||
real gamma, N_Vector ewt, real delta, long int *nfePtr,
|
||||
N_Vector r, int lr, void *bp_data, N_Vector z);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,191 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : cvdense.h *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 24 February 2000 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the header file for the CVODE dense linear solver, *
|
||||
* CVDENSE. *
|
||||
* *
|
||||
* Note: The type integer must be large enough to store the value *
|
||||
* of the linear system size N. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#ifdef __cplusplus /* wrapper to enable C++ usage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _cvdense_h
|
||||
#define _cvdense_h
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cvode.h"
|
||||
#include "llnltyps.h"
|
||||
#include "dense.h"
|
||||
#include "nvector.h"
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* CVDENSE solver statistics indices *
|
||||
*----------------------------------------------------------------*
|
||||
* The following enumeration gives a symbolic name to each *
|
||||
* CVDENSE statistic. The symbolic names are used as indices into *
|
||||
* the iopt and ropt arrays passed to CVodeMalloc. *
|
||||
* The CVDENSE statistics are: *
|
||||
* *
|
||||
* iopt[DENSE_NJE] : number of Jacobian evaluations, i.e. of *
|
||||
* calls made to the dense Jacobian routine *
|
||||
* (default or user-supplied). *
|
||||
* *
|
||||
* iopt[DENSE_LRW] : size (in real words) of real workspace *
|
||||
* matrices and vectors used by this solver. *
|
||||
* *
|
||||
* iopt[DENSE_LIW] : size (in integer words) of integer *
|
||||
* workspace vectors used by this solver. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
enum { DENSE_NJE=CVODE_IOPT_SIZE, DENSE_LRW, DENSE_LIW };
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* CVDENSE solver constants *
|
||||
*----------------------------------------------------------------*
|
||||
* CVD_MSBJ : maximum number of steps between dense Jacobian *
|
||||
* evaluations *
|
||||
* *
|
||||
* CVD_DGMAX : maximum change in gamma between dense Jacobian *
|
||||
* evaluations *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#define CVD_MSBJ 50
|
||||
|
||||
#define CVD_DGMAX RCONST(0.2)
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Type : CVDenseJacFn *
|
||||
*----------------------------------------------------------------*
|
||||
* A dense Jacobian approximation function Jac must have the *
|
||||
* prototype given below. Its parameters are: *
|
||||
* *
|
||||
* N is the length of all vector arguments. *
|
||||
* *
|
||||
* J is the dense matrix (of type DenseMat) that will be loaded *
|
||||
* by a CVDenseJacFn with an approximation to the Jacobian matrix *
|
||||
* J = (df_i/dy_j) at the point (t,y). *
|
||||
* J is preset to zero, so only the nonzero elements need to be *
|
||||
* loaded. Two efficient ways to load J are: *
|
||||
* *
|
||||
* (1) (with macros - no explicit data structure references) *
|
||||
* for (j=0; j < N; j++) { *
|
||||
* col_j = DENSE_COL(J,j); *
|
||||
* for (i=0; i < N; i++) { *
|
||||
* generate J_ij = the (i,j)th Jacobian element *
|
||||
* col_j[i] = J_ij; *
|
||||
* } *
|
||||
* } *
|
||||
* *
|
||||
* (2) (without macros - explicit data structure references) *
|
||||
* for (j=0; j < N; j++) { *
|
||||
* col_j = (J->data)[j]; *
|
||||
* for (i=0; i < N; i++) { *
|
||||
* generate J_ij = the (i,j)th Jacobian element *
|
||||
* col_j[i] = J_ij; *
|
||||
* } *
|
||||
* } *
|
||||
* *
|
||||
* The DENSE_ELEM(A,i,j) macro is appropriate for use in small *
|
||||
* problems in which efficiency of access is NOT a major concern. *
|
||||
* *
|
||||
* f is the right hand side function for the ODE problem. *
|
||||
* *
|
||||
* f_data is a pointer to user data to be passed to f, the same *
|
||||
* as the F_data parameter passed to CVodeMalloc. *
|
||||
* *
|
||||
* t is the current value of the independent variable. *
|
||||
* *
|
||||
* y is the current value of the dependent variable vector, *
|
||||
* namely the predicted value of y(t). *
|
||||
* *
|
||||
* fy is the vector f(t,y). *
|
||||
* *
|
||||
* ewt is the error weight vector. *
|
||||
* *
|
||||
* h is a tentative step size in t. *
|
||||
* *
|
||||
* uround is the machine unit roundoff. *
|
||||
* *
|
||||
* jac_data is a pointer to user data - the same as the jac_data *
|
||||
* parameter passed to CVDense. *
|
||||
* *
|
||||
* nfePtr is a pointer to the memory location containing the *
|
||||
* CVODE problem data nfe = number of calls to f. The Jacobian *
|
||||
* routine should update this counter by adding on the number *
|
||||
* of f calls made in order to approximate the Jacobian, if any. *
|
||||
* For example, if the routine calls f a total of N times, then *
|
||||
* the update is *nfePtr += N. *
|
||||
* *
|
||||
* vtemp1, vtemp2, and vtemp3 are pointers to memory allocated *
|
||||
* for vectors of length N which can be used by a CVDenseJacFn *
|
||||
* as temporary storage or work space. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
typedef void (*CVDenseJacFn)(integer N, DenseMat J, RhsFn f, void *f_data,
|
||||
real t, N_Vector y, N_Vector fy, N_Vector ewt,
|
||||
real h, real uround, void *jac_data,
|
||||
long int *nfePtr, N_Vector vtemp1,
|
||||
N_Vector vtemp2, N_Vector vtemp3);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : CVDense *
|
||||
*----------------------------------------------------------------*
|
||||
* A call to the CVDense function links the main CVODE integrator *
|
||||
* with the CVDENSE linear solver. *
|
||||
* *
|
||||
* cvode_mem is the pointer to CVODE memory returned by *
|
||||
* CVodeMalloc. *
|
||||
* *
|
||||
* djac is the dense Jacobian approximation routine to be used. *
|
||||
* A user-supplied djac routine must be of type *
|
||||
* CVDenseJacFn. Pass NULL for djac to use the default *
|
||||
* difference quotient routine CVDenseDQJac supplied *
|
||||
* with this solver. *
|
||||
* *
|
||||
* jac_data is a pointer to user data which is passed to the *
|
||||
* djac routine every time it is called. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void CVDense(void *cvode_mem, CVDenseJacFn djac, void *jac_data);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : CVDenseDQJac *
|
||||
*----------------------------------------------------------------*
|
||||
* This routine generates a dense difference quotient *
|
||||
* approximation to the Jacobian of f(t,y). *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void CVDenseDQJac(integer N, DenseMat J, RhsFn f, void *f_data, real t,
|
||||
N_Vector y, N_Vector fy, N_Vector ewt, real h, real uround,
|
||||
void *jac_data, long int *nfePtr, N_Vector vtemp1,
|
||||
N_Vector vtemp2, N_Vector vtemp3);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : cvdiag.h *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 4 May 1998 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the header file for the CVODE diagonal linear solver, *
|
||||
* CVDIAG. *
|
||||
* *
|
||||
* Note: The type integer must be large enough to store the value *
|
||||
* of the linear system size N. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
#ifdef __cplusplus /* wrapper to enable C++ usage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _cvdiag_h
|
||||
#define _cvdiag_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cvode.h"
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* CVDIAG solver statistics indices *
|
||||
*----------------------------------------------------------------*
|
||||
* The following enumeration gives a symbolic name to each *
|
||||
* CVDIAG statistic. The symbolic names are used as indices into *
|
||||
* the iopt and ropt arrays passed to CVodeMalloc. *
|
||||
* The CVDIAG statistics are: *
|
||||
* *
|
||||
* iopt[DIAG_LRW] : size (in real words) of real workspace *
|
||||
* vectors used by this solver. *
|
||||
* *
|
||||
* iopt[DIAG_LIW] : size (in integer words) of integer *
|
||||
* workspace vectors used by this solver. *
|
||||
* *
|
||||
* The number of diagonal approximate Jacobians formed is equal *
|
||||
* to the number of CVDiagSetup calls. This number is available *
|
||||
* in cv_iopt[NSETUPS]. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
enum { DIAG_LRW=CVODE_IOPT_SIZE, DIAG_LIW };
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : CVDiag *
|
||||
*----------------------------------------------------------------*
|
||||
* A call to the CVDiag function links the main CVODE integrator *
|
||||
* with the CVDIAG linear solver. *
|
||||
* *
|
||||
* cvode_mem is the pointer to CVODE memory returned by *
|
||||
* CVodeMalloc. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void CVDiag(void *cvode_mem);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,823 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : cvode.h *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 29 February 2000 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the interface file for the main CVODE integrator. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
#ifdef __cplusplus /* wrapper to enable C++ usage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _cvode_h
|
||||
#define _cvode_h
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* CVODE is used to solve numerically the ordinary initial value *
|
||||
* problem : *
|
||||
* *
|
||||
* y' = f(t,y), *
|
||||
* y(t0) = y0, *
|
||||
* *
|
||||
* where t0, y0 in R^N, and f: R x R^N -> R^N are given. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Enumerations for inputs to CVodeMalloc, CVReInit, and CVode. *
|
||||
*----------------------------------------------------------------*
|
||||
* Symbolic constants for the lmm, iter, and itol input *
|
||||
* parameters to CVodeMalloc and CVReInit, as well as the input *
|
||||
* parameter itask to CVode, are given below. *
|
||||
* *
|
||||
* lmm : The user of the CVODE package specifies whether to use *
|
||||
* the ADAMS or BDF (backward differentiation formula) *
|
||||
* linear multistep method. The BDF method is recommended *
|
||||
* for stiff problems, and the ADAMS method is recommended *
|
||||
* for nonstiff problems. *
|
||||
* *
|
||||
* iter : At each internal time step, a nonlinear equation must *
|
||||
* be solved. The user can specify either FUNCTIONAL *
|
||||
* iteration, which does not require linear algebra, or a *
|
||||
* NEWTON iteration, which requires the solution of linear *
|
||||
* systems. In the NEWTON case, the user also specifies a *
|
||||
* CVODE linear solver. NEWTON is recommended in case of *
|
||||
* stiff problems. *
|
||||
* *
|
||||
* itol : This parameter specifies the relative and absolute *
|
||||
* tolerance types to be used. The SS tolerance type means *
|
||||
* a scalar relative and absolute tolerance, while the SV *
|
||||
* tolerance type means a scalar relative tolerance and a *
|
||||
* vector absolute tolerance (a potentially different *
|
||||
* absolute tolerance for each vector component). *
|
||||
* *
|
||||
* itask : The itask input parameter to CVode indicates the job *
|
||||
* of the solver for the next user step. The NORMAL *
|
||||
* itask is to have the solver take internal steps until *
|
||||
* it has reached or just passed the user specified tout *
|
||||
* parameter. The solver then interpolates in order to *
|
||||
* return an approximate value of y(tout). The ONE_STEP *
|
||||
* option tells the solver to just take one internal step *
|
||||
* and return the solution at the point reached by that *
|
||||
* step. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
enum { ADAMS, BDF }; /* lmm */
|
||||
|
||||
enum { FUNCTIONAL, NEWTON }; /* iter */
|
||||
|
||||
enum { SS, SV }; /* itol */
|
||||
|
||||
enum { NORMAL, ONE_STEP }; /* itask */
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Type : RhsFn *
|
||||
*----------------------------------------------------------------*
|
||||
* The f function which defines the right hand side of the ODE *
|
||||
* system y' = f(t,y) must have type RhsFn. *
|
||||
* f takes as input the problem size N, the independent variable *
|
||||
* value t, and the dependent variable vector y. It stores the *
|
||||
* result of f(t,y) in the vector ydot. The y and ydot arguments *
|
||||
* are of type N_Vector. *
|
||||
* (Allocation of memory for ydot is handled within CVODE.) *
|
||||
* The f_data parameter is the same as the f_data *
|
||||
* parameter passed by the user to the CVodeMalloc routine. This *
|
||||
* user-supplied pointer is passed to the user's f function *
|
||||
* every time it is called. *
|
||||
* A RhsFn f does not have a return value. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
typedef void (*RhsFn)(integer N, real t, N_Vector y, N_Vector ydot,
|
||||
void *f_data);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : CVodeMalloc *
|
||||
*----------------------------------------------------------------*
|
||||
* CVodeMalloc allocates and initializes memory for a problem to *
|
||||
* to be solved by CVODE. *
|
||||
* *
|
||||
* N is the number of equations in the ODE system. *
|
||||
* *
|
||||
* f is the right hand side function in y' = f(t,y). *
|
||||
* *
|
||||
* t0 is the initial value of t. *
|
||||
* *
|
||||
* y0 is the initial condition vector y(t0). *
|
||||
* *
|
||||
* lmm is the type of linear multistep method to be used. *
|
||||
* The legal values are ADAMS and BDF (see previous *
|
||||
* description). *
|
||||
* *
|
||||
* iter is the type of iteration used to solve the nonlinear *
|
||||
* system that arises during each internal time step. *
|
||||
* The legal values are FUNCTIONAL and NEWTON. *
|
||||
* *
|
||||
* itol is the type of tolerances to be used. *
|
||||
* The legal values are: *
|
||||
* SS (scalar relative and absolute tolerances), *
|
||||
* SV (scalar relative tolerance and vector *
|
||||
* absolute tolerance). *
|
||||
* *
|
||||
* reltol is a pointer to the relative tolerance scalar. *
|
||||
* *
|
||||
* abstol is a pointer to the absolute tolerance scalar or *
|
||||
* an N_Vector of absolute tolerances. *
|
||||
* *
|
||||
* The parameters itol, reltol, and abstol define a vector of *
|
||||
* error weights, ewt, with components *
|
||||
* ewt[i] = 1/(reltol*abs(y[i]) + abstol) (if itol = SS), or *
|
||||
* ewt[i] = 1/(reltol*abs(y[i]) + abstol[i]) (if itol = SV). *
|
||||
* This vector is used in all error and convergence tests, which *
|
||||
* use a weighted RMS norm on all error-like vectors v: *
|
||||
* WRMSnorm(v) = sqrt( (1/N) sum(i=1..N) (v[i]*ewt[i])^2 ). *
|
||||
* *
|
||||
* f_data is a pointer to user data that will be passed to the *
|
||||
* user's f function every time f is called. *
|
||||
* *
|
||||
* errfp is the file pointer for an error file where all CVODE *
|
||||
* warning and error messages will be written. This *
|
||||
* parameter can be stdout (standard output), stderr *
|
||||
* (standard error), a file pointer (corresponding to *
|
||||
* a user error file opened for writing) returned by *
|
||||
* fopen, or NULL. If the user passes NULL, then all *
|
||||
* messages will be written to standard output. *
|
||||
* *
|
||||
* optIn is a flag indicating whether there are any optional *
|
||||
* inputs from the user in the arrays iopt and ropt. *
|
||||
* Pass FALSE to indicate no optional inputs and TRUE *
|
||||
* to indicate that optional inputs are present. *
|
||||
* *
|
||||
* iopt is the user-allocated array (of size OPT_SIZE given *
|
||||
* later) that will hold optional integer inputs and *
|
||||
* outputs. The user can pass NULL if he/she does not *
|
||||
* wish to use optional integer inputs or outputs. *
|
||||
* If optIn is TRUE, the user should preset to 0 those *
|
||||
* locations for which default values are to be used. *
|
||||
* *
|
||||
* ropt is the user-allocated array (of size OPT_SIZE given *
|
||||
* later) that will hold optional real inputs and *
|
||||
* outputs. The user can pass NULL if he/she does not *
|
||||
* wish to use optional real inputs or outputs. *
|
||||
* If optIn is TRUE, the user should preset to 0.0 the *
|
||||
* locations for which default values are to be used. *
|
||||
* *
|
||||
* machEnv is a pointer to machine environment-specific *
|
||||
* information. *
|
||||
* *
|
||||
* Note: The tolerance values may be changed in between calls to *
|
||||
* CVode for the same problem. These values refer to *
|
||||
* (*reltol) and either (*abstol), for a scalar absolute *
|
||||
* tolerance, or the components of abstol, for a vector *
|
||||
* absolute tolerance. *
|
||||
* *
|
||||
* If successful, CVodeMalloc returns a pointer to initialized *
|
||||
* problem memory. This pointer should be passed to CVode. If *
|
||||
* an initialization error occurs, CVodeMalloc prints an error *
|
||||
* message to the file specified by errfp and returns NULL. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
void *CVodeMalloc(integer N, RhsFn f, real t0, N_Vector y0, int lmm, int iter,
|
||||
int itol, real *reltol, void *abstol, void *f_data,
|
||||
FILE *errfp, boole optIn, long int iopt[], real ropt[],
|
||||
void *machEnv);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : CVReInit *
|
||||
*----------------------------------------------------------------*
|
||||
* CVReInit re-initializes CVode for the solution of a problem, *
|
||||
* where a prior call to CVodeMalloc has been made with the same *
|
||||
* problem size N. CVReInit performs the same input checking *
|
||||
* and initializations that CVodeMalloc does (except for N). *
|
||||
* But it does no memory allocation, assuming that the existing *
|
||||
* internal memory is sufficient for the new problem. *
|
||||
* *
|
||||
* The use of CVReInit requires that the maximum method order, *
|
||||
* maxord, is no larger for the new problem than for the problem *
|
||||
* specified in the last call to CVodeMalloc. This condition is *
|
||||
* automatically fulfilled if the multistep method parameter lmm *
|
||||
* is unchanged (or changed from ADAMS to BDF) and the default *
|
||||
* value for maxord is specified. *
|
||||
* *
|
||||
* The first argument to CVReInit is: *
|
||||
* *
|
||||
* cvode_mem = pointer to CVODE memory returned by CVodeMalloc. *
|
||||
* *
|
||||
* All the remaining arguments to CVReInit have names and *
|
||||
* meanings identical to those of CVodeMalloc. Note that the *
|
||||
* problem size N is not passed as an argument to CVReInit, *
|
||||
* as that is assumed to unchanged since the CVodeMalloc call. *
|
||||
* *
|
||||
* The return value of CVReInit is equal to SUCCESS = 0 if there *
|
||||
* were no errors; otherwise it is a negative int equal to: *
|
||||
* CVREI_NO_MEM indicating cvode_mem was NULL, or *
|
||||
* CVREI_ILL_INPUT indicating an input argument was illegal *
|
||||
* (including an attempt to increase maxord). *
|
||||
* In case of an error return, an error message is also printed. *
|
||||
* *
|
||||
* Note: the reported workspace sizes iopt[LENRW] and iopt[LENIW] *
|
||||
* are left unchanged from the values computed by CVodeMalloc, and*
|
||||
* so may be larger than would be computed for the new problem. *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
int CVReInit(void *cvode_mem, RhsFn f, real t0, N_Vector y0,
|
||||
int lmm, int iter, int itol, real *reltol, void *abstol,
|
||||
void *f_data, FILE *errfp, boole optIn, long int iopt[],
|
||||
real ropt[], void *machEnv);
|
||||
|
||||
|
||||
/* CVReInit return values: */
|
||||
|
||||
/* SUCCESS = 0 (Defined under CVode return values, but listed
|
||||
here also for completeness) */
|
||||
enum {CVREI_NO_MEM = -1, CVREI_ILL_INPUT = -2};
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : CVode *
|
||||
*----------------------------------------------------------------*
|
||||
* CVode integrates the ODE over an interval in t. *
|
||||
* If itask is NORMAL, then the solver integrates from its *
|
||||
* current internal t value to a point at or beyond tout, then *
|
||||
* interpolates to t = tout and returns y(tout) in the user- *
|
||||
* allocated vector yout. If itask is ONE_STEP, then the solver *
|
||||
* takes one internal time step and returns in yout the value of *
|
||||
* y at the new internal time. In this case, tout is used only *
|
||||
* during the first call to CVode to determine the direction of *
|
||||
* integration and the rough scale of the problem. In either *
|
||||
* case, the time reached by the solver is placed in (*t). The *
|
||||
* user is responsible for allocating the memory for this value. *
|
||||
* *
|
||||
* cvode_mem is the pointer to CVODE memory returned by *
|
||||
* CVodeMalloc. *
|
||||
* *
|
||||
* tout is the next time at which a computed solution is desired *
|
||||
* *
|
||||
* yout is the computed solution vector. In NORMAL mode with no *
|
||||
* errors, yout=y(tout). *
|
||||
* *
|
||||
* t is a pointer to a real location. CVode sets (*t) to the *
|
||||
* time reached by the solver and returns yout=y(*t). *
|
||||
* *
|
||||
* itask is either NORMAL or ONE_STEP mode. These two modes have *
|
||||
* described above. *
|
||||
* *
|
||||
* The return values for CVode are defined later in this file. *
|
||||
* Here is a brief description of each return value: *
|
||||
* *
|
||||
* SUCCESS : CVode succeeded. *
|
||||
* *
|
||||
* CVODE_NO_MEM : The cvode_mem argument was NULL. *
|
||||
* *
|
||||
* ILL_INPUT : One of the inputs to CVode is illegal. This *
|
||||
* includes the situation when a component of the *
|
||||
* error weight vectors becomes < 0 during *
|
||||
* internal time-stepping. The ILL_INPUT flag *
|
||||
* will also be returned if the linear solver *
|
||||
* routine CV--- (called by the user after *
|
||||
* calling CVodeMalloc) failed to set one of the *
|
||||
* linear solver-related fields in cvode_mem or *
|
||||
* if the linear solver's init routine failed. In *
|
||||
* any case, the user should see the printed *
|
||||
* error message for more details. *
|
||||
* *
|
||||
* TOO_MUCH_WORK : The solver took mxstep internal steps but *
|
||||
* could not reach tout. The default value for *
|
||||
* mxstep is MXSTEP_DEFAULT = 500. *
|
||||
* *
|
||||
* TOO_MUCH_ACC : The solver could not satisfy the accuracy *
|
||||
* demanded by the user for some internal step. *
|
||||
* *
|
||||
* ERR_FAILURE : Error test failures occurred too many times *
|
||||
* (= MXNEF = 7) during one internal time step or *
|
||||
* occurred with |h| = hmin. *
|
||||
* *
|
||||
* CONV_FAILURE : Convergence test failures occurred too many *
|
||||
* times (= MXNCF = 10) during one internal time *
|
||||
* step or occurred with |h| = hmin. *
|
||||
* *
|
||||
* SETUP_FAILURE : The linear solver's setup routine failed in an *
|
||||
* unrecoverable manner. *
|
||||
* *
|
||||
* SOLVE_FAILURE : The linear solver's solve routine failed in an *
|
||||
* unrecoverable manner. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
int CVode(void *cvode_mem, real tout, N_Vector yout, real *t, int itask);
|
||||
|
||||
|
||||
/* CVode return values */
|
||||
|
||||
enum { SUCCESS=0, CVODE_NO_MEM=-1, ILL_INPUT=-2, TOO_MUCH_WORK=-3,
|
||||
TOO_MUCH_ACC=-4, ERR_FAILURE=-5, CONV_FAILURE=-6,
|
||||
SETUP_FAILURE=-7, SOLVE_FAILURE=-8 };
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : CVodeDky *
|
||||
*----------------------------------------------------------------*
|
||||
* CVodeDky computes the kth derivative of the y function at *
|
||||
* time t, where tn-hu <= t <= tn, tn denotes the current *
|
||||
* internal time reached, and hu is the last internal step size *
|
||||
* successfully used by the solver. The user may request *
|
||||
* k=0, 1, ..., qu, where qu is the current order. The *
|
||||
* derivative vector is returned in dky. This vector must be *
|
||||
* allocated by the caller. It is only legal to call this *
|
||||
* function after a successful return from CVode. *
|
||||
* *
|
||||
* cvode_mem is the pointer to CVODE memory returned by *
|
||||
* CVodeMalloc. *
|
||||
* *
|
||||
* t is the time at which the kth derivative of y is evaluated. *
|
||||
* The legal range for t is [tn-hu,tn] as described above. *
|
||||
* *
|
||||
* k is the order of the derivative of y to be computed. The *
|
||||
* legal range for k is [0,qu] as described above. *
|
||||
* *
|
||||
* dky is the output derivative vector [(D_k)y](t). *
|
||||
* *
|
||||
* The return values for CVodeDky are defined later in this file. *
|
||||
* Here is a brief description of each return value: *
|
||||
* *
|
||||
* OKAY : CVodeDky succeeded. *
|
||||
* *
|
||||
* BAD_K : k is not in the range 0, 1, ..., qu. *
|
||||
* *
|
||||
* BAD_T : t is not in the interval [tn-hu,tn]. *
|
||||
* *
|
||||
* BAD_DKY : The dky argument was NULL. *
|
||||
* *
|
||||
* DKY_NO_MEM : The cvode_mem argument was NULL. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
int CVodeDky(void *cvode_mem, real t, int k, N_Vector dky);
|
||||
|
||||
|
||||
/* CVodeDky return values */
|
||||
|
||||
enum { OKAY=0, BAD_K=-1, BAD_T=-2, BAD_DKY=-3, DKY_NO_MEM=-4 };
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : CVodeFree *
|
||||
*----------------------------------------------------------------*
|
||||
* CVodeFree frees the problem memory cvode_mem allocated by *
|
||||
* CVodeMalloc. Its only argument is the pointer cvode_mem *
|
||||
* returned by CVodeMalloc. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void CVodeFree(void *cvode_mem);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Optional Inputs and Outputs *
|
||||
*----------------------------------------------------------------*
|
||||
* The user should declare two arrays for optional input and *
|
||||
* output, an iopt array for optional integer input and output *
|
||||
* and an ropt array for optional real input and output. The *
|
||||
* size of both these arrays should be OPT_SIZE. *
|
||||
* So the user's declaration should look like: *
|
||||
* *
|
||||
* long int iopt[OPT_SIZE]; *
|
||||
* real ropt[OPT_SIZE]; *
|
||||
* *
|
||||
* The enumerations below the OPT_SIZE definition *
|
||||
* are indices into the iopt and ropt arrays. Here is a brief *
|
||||
* description of the contents of these positions: *
|
||||
* *
|
||||
* iopt[MAXORD] : maximum lmm order to be used by the solver. *
|
||||
* Optional input. (Default = 12 for ADAMS, 5 for *
|
||||
* BDF). *
|
||||
* *
|
||||
* iopt[MXSTEP] : maximum number of internal steps to be taken by *
|
||||
* the solver in its attempt to reach tout. *
|
||||
* Optional input. (Default = 500). *
|
||||
* *
|
||||
* iopt[MXHNIL] : maximum number of warning messages issued *
|
||||
* by the solver that t+h==t on the next internal *
|
||||
* step. Optional input. (Default = 10). *
|
||||
* *
|
||||
* iopt[NST] : cumulative number of internal steps taken by *
|
||||
* the solver (total so far). Optional output. *
|
||||
* *
|
||||
* iopt[NFE] : number of calls to the user's f function. *
|
||||
* Optional output. *
|
||||
* *
|
||||
* iopt[NSETUPS] : number of calls made to the linear solver's *
|
||||
* setup routine. Optional output. *
|
||||
* *
|
||||
* iopt[NNI] : number of NEWTON iterations performed. *
|
||||
* Optional output. *
|
||||
* *
|
||||
* iopt[NCFN] : number of nonlinear convergence failures *
|
||||
* that have occurred. Optional output. *
|
||||
* *
|
||||
* iopt[NETF] : number of local error test failures that *
|
||||
* have occurred. Optional output. *
|
||||
* *
|
||||
* iopt[QU] : order used during the last internal step. *
|
||||
* Optional output. *
|
||||
* *
|
||||
* iopt[QCUR] : order to be used on the next internal step. *
|
||||
* Optional output. *
|
||||
* *
|
||||
* iopt[LENRW] : size of required CVODE internal real work *
|
||||
* space, in real words. Optional output. *
|
||||
* *
|
||||
* iopt[LENIW] : size of required CVODE internal integer work *
|
||||
* space, in integer words. Optional output. *
|
||||
* *
|
||||
* ropt[H0] : initial step size. Optional input. *
|
||||
* *
|
||||
* ropt[HMAX] : maximum absolute value of step size allowed. *
|
||||
* Optional input. (Default is infinity). *
|
||||
* *
|
||||
* ropt[HMIN] : minimum absolute value of step size allowed. *
|
||||
* Optional input. (Default is 0.0). *
|
||||
* *
|
||||
* ropt[HU] : step size for the last internal step. *
|
||||
* Optional output. *
|
||||
* *
|
||||
* ropt[HCUR] : step size to be attempted on the next internal *
|
||||
* step. Optional output. *
|
||||
* *
|
||||
* ropt[TCUR] : current internal time reached by the solver. *
|
||||
* Optional output. *
|
||||
* *
|
||||
* ropt[TOLSF] : a suggested factor by which the user's *
|
||||
* tolerances should be scaled when too much *
|
||||
* accuracy has been requested for some internal *
|
||||
* step. Optional output. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
/* iopt, ropt array sizes */
|
||||
|
||||
#define OPT_SIZE 40
|
||||
|
||||
|
||||
/* iopt and ropt offsets *
|
||||
* The constants CVODE_IOPT_SIZE and CVODE_ROPT_SIZE are equal to *
|
||||
* the number of integer and real optional inputs and outputs *
|
||||
* actually accessed in cvode.c. The locations beyond these *
|
||||
* values are used by the linear solvers. */
|
||||
|
||||
#define CVODE_IOPT_SIZE 13
|
||||
#define CVODE_ROPT_SIZE 7
|
||||
|
||||
/* iopt indices */
|
||||
|
||||
enum { MAXORD, MXSTEP, MXHNIL,
|
||||
NST, NFE, NSETUPS, NNI, NCFN, NETF, QU, QCUR,
|
||||
LENRW, LENIW };
|
||||
|
||||
/* ropt indices */
|
||||
|
||||
enum { H0, HMAX, HMIN,
|
||||
HU, HCUR, TCUR, TOLSF };
|
||||
|
||||
|
||||
/* Basic CVODE constants */
|
||||
|
||||
#define ADAMS_Q_MAX 12 /* max value of q for lmm == ADAMS */
|
||||
#define BDF_Q_MAX 5 /* max value of q for lmm == BDF */
|
||||
#define Q_MAX ADAMS_Q_MAX /* max value of q for either lmm */
|
||||
#define L_MAX (Q_MAX+1) /* max value of L for either lmm */
|
||||
#define NUM_TESTS 5 /* number of error test quantities */
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Types : struct CVodeMemRec, CVodeMem *
|
||||
*----------------------------------------------------------------*
|
||||
* The type CVodeMem is type pointer to struct CVodeMemRec. This *
|
||||
* structure contains fields to keep track of problem state. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
typedef struct CVodeMemRec {
|
||||
|
||||
real cv_uround; /* machine unit roundoff */
|
||||
|
||||
/* Problem Specification Data */
|
||||
|
||||
integer cv_N; /* ODE system size */
|
||||
RhsFn cv_f; /* y' = f(t,y(t)) */
|
||||
void *cv_f_data; /* user pointer passed to f */
|
||||
int cv_lmm; /* lmm = ADAMS or BDF */
|
||||
int cv_iter; /* iter = FUNCTIONAL or NEWTON */
|
||||
int cv_itol; /* itol = SS or SV */
|
||||
real *cv_reltol; /* ptr to relative tolerance */
|
||||
void *cv_abstol; /* ptr to absolute tolerance */
|
||||
|
||||
/* Nordsieck History Array */
|
||||
|
||||
N_Vector cv_zn[L_MAX]; /* Nordsieck array N x (q+1), */
|
||||
/* zn[j] is a vector of length N, j=0, ... , q */
|
||||
/* zn[j] = h^j * jth derivative of the */
|
||||
/* interpolating polynomial */
|
||||
|
||||
/* Vectors of length N */
|
||||
|
||||
N_Vector cv_ewt; /* error weight vector */
|
||||
N_Vector cv_y; /* y is used as temporary storage by the solver */
|
||||
/* The memory is provided by the user to CVode */
|
||||
/* where the vector is named yout. */
|
||||
N_Vector cv_acor; /* In the context of the solution of the */
|
||||
/* nonlinear equation, acor = y_n(m) - y_n(0). */
|
||||
/* On return, this vector is scaled to give */
|
||||
/* the estimated local error in y. */
|
||||
N_Vector cv_tempv; /* temporary storage vector */
|
||||
N_Vector cv_ftemp; /* temporary storage vector */
|
||||
|
||||
/* Step Data */
|
||||
|
||||
int cv_q; /* current order */
|
||||
int cv_qprime; /* order to be used on the next step */
|
||||
/* = q-1, q, or q+1 */
|
||||
int cv_qwait; /* number of internal steps to wait before */
|
||||
/* considering a change in q */
|
||||
int cv_L; /* L = q + 1 */
|
||||
|
||||
real cv_h; /* current step size */
|
||||
real cv_hprime; /* step size to be used on the next step */
|
||||
real cv_eta; /* eta = hprime / h */
|
||||
real cv_hscale; /* value of h used in zn */
|
||||
real cv_tn; /* current internal value of t */
|
||||
|
||||
real cv_tau[L_MAX+1]; /* array of previous q+1 successful step */
|
||||
/* sizes indexed from 1 to q+1 */
|
||||
real cv_tq[NUM_TESTS+1]; /* array of test quantities indexed from */
|
||||
/* 1 to NUM_TESTS(=5) */
|
||||
real cv_l[L_MAX]; /* coefficients of l(x) (degree q poly) */
|
||||
|
||||
real cv_rl1; /* 1 / l[1] */
|
||||
real cv_gamma; /* gamma = h * rl1 */
|
||||
real cv_gammap; /* gamma at the last setup call */
|
||||
real cv_gamrat; /* gamma / gammap */
|
||||
|
||||
real cv_crate; /* estimated corrector convergence rate */
|
||||
real cv_acnrm; /* | acor | wrms */
|
||||
int cv_mnewt; /* Newton iteration counter */
|
||||
|
||||
/* Limits */
|
||||
|
||||
int cv_qmax; /* q <= qmax */
|
||||
int cv_mxstep; /* maximum number of internal steps for one user call */
|
||||
int cv_maxcor; /* maximum number of corrector iterations for the */
|
||||
/* solution of the nonlinear equation */
|
||||
int cv_mxhnil; /* maximum number of warning messages issued to the */
|
||||
/* user that t + h == t for the next internal step */
|
||||
|
||||
real cv_hmin; /* |h| >= hmin */
|
||||
real cv_hmax_inv; /* |h| <= 1/hmax_inv */
|
||||
real cv_etamax; /* eta <= etamax */
|
||||
|
||||
/* Counters */
|
||||
|
||||
long int cv_nst; /* number of internal steps taken */
|
||||
long int cv_nfe; /* number of f calls */
|
||||
long int cv_ncfn; /* number of corrector convergence failures */
|
||||
long int cv_netf; /* number of error test failures */
|
||||
long int cv_nni; /* number of Newton iterations performed */
|
||||
long int cv_nsetups; /* number of setup calls */
|
||||
int cv_nhnil; /* number of messages issued to the user that */
|
||||
/* t + h == t for the next iternal step */
|
||||
long int cv_lrw; /* number of real words in CVODE work vectors */
|
||||
long int cv_liw; /* no. of integer words in CVODE work vectors */
|
||||
|
||||
/* Linear Solver Data */
|
||||
|
||||
/* Linear Solver functions to be called */
|
||||
|
||||
int (*cv_linit)(struct CVodeMemRec *cv_mem, boole *setupNonNull);
|
||||
|
||||
int (*cv_lsetup)(struct CVodeMemRec *cv_mem, int convfail, N_Vector ypred,
|
||||
N_Vector fpred, boole *jcurPtr, N_Vector vtemp1,
|
||||
N_Vector vtemp2, N_Vector vtemp3);
|
||||
|
||||
int (*cv_lsolve)(struct CVodeMemRec *cv_mem, N_Vector b, N_Vector ycur,
|
||||
N_Vector fcur);
|
||||
|
||||
void (*cv_lfree)(struct CVodeMemRec *cv_mem);
|
||||
|
||||
/* Linear Solver specific memory */
|
||||
|
||||
void *cv_lmem;
|
||||
|
||||
/* Flag to indicate successful cv_linit call */
|
||||
|
||||
boole cv_linitOK;
|
||||
|
||||
/* Saved Values */
|
||||
|
||||
int cv_qu; /* last successful q value used */
|
||||
long int cv_nstlp; /* step number of last setup call */
|
||||
real cv_hu; /* last successful h value used */
|
||||
real cv_saved_tq5; /* saved value of tq[5] */
|
||||
boole cv_jcur; /* Is the Jacobian info used by */
|
||||
/* linear solver current? */
|
||||
real cv_tolsf; /* tolerance scale factor */
|
||||
boole cv_setupNonNull;/* Does setup do something? */
|
||||
|
||||
/* Arrays for Optional Input and Optional Output */
|
||||
|
||||
long int *cv_iopt; /* long int optional input, output */
|
||||
real *cv_ropt; /* real optional input, output */
|
||||
|
||||
/* Error File */
|
||||
|
||||
FILE *cv_errfp; /* CVODE error messages are sent to errfp */
|
||||
|
||||
/* Pointer to Machine Environment-Specific Information */
|
||||
|
||||
void *cv_machenv;
|
||||
|
||||
} *CVodeMem;
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Communication between cvode.c and a CVODE Linear Solver *
|
||||
*----------------------------------------------------------------*
|
||||
* (1) cv_linit return values *
|
||||
* *
|
||||
* LINIT_OK : The cv_linit routine succeeded. *
|
||||
* *
|
||||
* LINIT_ERR : The cv_linit routine failed. Each linear solver *
|
||||
* init routine should print an appropriate error *
|
||||
* message to (cv_mem->errfp). *
|
||||
* *
|
||||
* (2) convfail (input to cv_lsetup) *
|
||||
* *
|
||||
* NO_FAILURES : Either this is the first cv_setup call for this *
|
||||
* step, or the local error test failed on the *
|
||||
* previous attempt at this step (but the Newton *
|
||||
* iteration converged). *
|
||||
* *
|
||||
* FAIL_BAD_J : This value is passed to cv_lsetup if *
|
||||
* *
|
||||
* (1) The previous Newton corrector iteration *
|
||||
* did not converge and the linear solver's *
|
||||
* setup routine indicated that its Jacobian- *
|
||||
* related data is not current. *
|
||||
* or *
|
||||
* (2) During the previous Newton corrector *
|
||||
* iteration, the linear solver's solve routine *
|
||||
* failed in a recoverable manner and the *
|
||||
* linear solver's setup routine indicated that *
|
||||
* its Jacobian-related data is not current. *
|
||||
* *
|
||||
* FAIL_OTHER : During the current internal step try, the *
|
||||
* previous Newton iteration failed to converge *
|
||||
* even though the linear solver was using current *
|
||||
* Jacobian-related data. *
|
||||
* *
|
||||
* (3) Parameter documentation, as well as a brief description *
|
||||
* of purpose, for each CVODE linear solver routine to be *
|
||||
* called in cvode.c is given below the constant declarations *
|
||||
* that follow. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
/* cv_linit return values */
|
||||
|
||||
#define LINIT_OK 0
|
||||
#define LINIT_ERR -1
|
||||
|
||||
/* Constants for convfail (input to cv_lsetup) */
|
||||
|
||||
#define NO_FAILURES 0
|
||||
#define FAIL_BAD_J 1
|
||||
#define FAIL_OTHER 2
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* *
|
||||
* int (*cv_linit)(CVodeMem cv_mem, boole *setupNonNull); *
|
||||
*-----------------------------------------------------------------*
|
||||
* The purpose of cv_linit is to allocate memory for the *
|
||||
* solver-specific fields in the structure *(cv_mem->cv_lmem) and *
|
||||
* perform any needed initializations of solver-specific memory, *
|
||||
* such as counters/statistics. The cv_linit routine should set *
|
||||
* *setupNonNull to be TRUE if the setup operation for the linear *
|
||||
* solver is non-empty and FALSE if the setup operation does *
|
||||
* nothing. An LInitFn should return LINIT_OK (== 0) if it has *
|
||||
* successfully initialized the CVODE linear solver and LINIT_ERR *
|
||||
* (== -1) otherwise. These constants are defined above. If an *
|
||||
* error does occur, an appropriate message should be sent to *
|
||||
* (cv_mem->errfp). *
|
||||
* *
|
||||
*******************************************************************/
|
||||
|
||||
/*******************************************************************
|
||||
* *
|
||||
* int (*cv_lsetup)(CVodeMem cv_mem, int convfail, N_Vector ypred, *
|
||||
* N_Vector fpred, boole *jcurPtr, N_Vector vtemp1,*
|
||||
* N_Vector vtemp2, N_Vector vtemp3); *
|
||||
*-----------------------------------------------------------------*
|
||||
* The job of cv_lsetup is to prepare the linear solver for *
|
||||
* subsequent calls to cv_lsolve. It may re-compute Jacobian- *
|
||||
* related data is it deems necessary. Its parameters are as *
|
||||
* follows: *
|
||||
* *
|
||||
* cv_mem - problem memory pointer of type CVodeMem. See the big *
|
||||
* typedef earlier in this file. *
|
||||
* *
|
||||
* convfail - a flag to indicate any problem that occurred during *
|
||||
* the solution of the nonlinear equation on the *
|
||||
* current time step for which the linear solver is *
|
||||
* being used. This flag can be used to help decide *
|
||||
* whether the Jacobian data kept by a CVODE linear *
|
||||
* solver needs to be updated or not. *
|
||||
* Its possible values have been documented above. *
|
||||
* *
|
||||
* ypred - the predicted y vector for the current CVODE internal *
|
||||
* step. *
|
||||
* *
|
||||
* fpred - f(tn, ypred). *
|
||||
* *
|
||||
* jcurPtr - a pointer to a boolean to be filled in by cv_lsetup. *
|
||||
* The function should set *jcurPtr=TRUE if its Jacobian *
|
||||
* data is current after the call and should set *
|
||||
* *jcurPtr=FALSE if its Jacobian data is not current. *
|
||||
* Note: If cv_lsetup calls for re-evaluation of *
|
||||
* Jacobian data (based on convfail and CVODE state *
|
||||
* data), it should return *jcurPtr=TRUE unconditionally;*
|
||||
* otherwise an infinite loop can result. *
|
||||
* *
|
||||
* vtemp1 - temporary N_Vector provided for use by cv_lsetup. *
|
||||
* *
|
||||
* vtemp3 - temporary N_Vector provided for use by cv_lsetup. *
|
||||
* *
|
||||
* vtemp3 - temporary N_Vector provided for use by cv_lsetup. *
|
||||
* *
|
||||
* The cv_lsetup routine should return 0 if successful, *
|
||||
* a positive value for a recoverable error, and a negative value *
|
||||
* for an unrecoverable error. *
|
||||
* *
|
||||
*******************************************************************/
|
||||
|
||||
/*******************************************************************
|
||||
* *
|
||||
* int (*cv_lsolve)(CVodeMem cv_mem, N_Vector b, N_Vector ycur, *
|
||||
* N_Vector fcur); *
|
||||
*-----------------------------------------------------------------*
|
||||
* cv_lsolve must solve the linear equation P x = b, where *
|
||||
* P is some approximation to (I - gamma J), J = (df/dy)(tn,ycur) *
|
||||
* and the RHS vector b is input. The N-vector ycur contains *
|
||||
* the solver's current approximation to y(tn) and the vector *
|
||||
* fcur contains the N-vector f(tn,ycur). The solution is to be *
|
||||
* returned in the vector b. cv_lsolve returns a positive value *
|
||||
* for a recoverable error and a negative value for an *
|
||||
* unrecoverable error. Success is indicated by a 0 return value. *
|
||||
* *
|
||||
*******************************************************************/
|
||||
|
||||
/*******************************************************************
|
||||
* *
|
||||
* void (*cv_lfree)(CVodeMem cv_mem); *
|
||||
*-----------------------------------------------------------------*
|
||||
* cv_lfree should free up any memory allocated by the linear *
|
||||
* solver. This routine is called once a problem has been *
|
||||
* completed and the linear solver is no longer needed. *
|
||||
* *
|
||||
*******************************************************************/
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,336 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : cvspgmr.h *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 4 May 1998 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the header file for the CVODE scaled, preconditioned *
|
||||
* GMRES linear solver, CVSPGMR. *
|
||||
* *
|
||||
* Note: The type integer must be large enough to store the value *
|
||||
* of the linear system size N. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
#ifdef __cplusplus /* wrapper to enable C++ usage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _cvspgmr_h
|
||||
#define _cvspgmr_h
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cvode.h"
|
||||
#include "spgmr.h"
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* CVSPGMR solver statistics indices *
|
||||
*----------------------------------------------------------------*
|
||||
* The following enumeration gives a symbolic name to each *
|
||||
* CVSPGMR statistic. The symbolic names are used as indices into *
|
||||
* the iopt and ropt arrays passed to CVodeMalloc. *
|
||||
* The CVSPGMR statistics are: *
|
||||
* *
|
||||
* iopt[SPGMR_NPE] : number of preconditioner evaluations, *
|
||||
* i.e. of calls made to user's precond *
|
||||
* function with jok == FALSE. *
|
||||
* *
|
||||
* iopt[SPGMR_NLI] : number of linear iterations. *
|
||||
* *
|
||||
* iopt[SPGMR_NPS] : number of calls made to user's psolve *
|
||||
* function. *
|
||||
* *
|
||||
* iopt[SPGMR_NCFL] : number of linear convergence failures. *
|
||||
* *
|
||||
* iopt[SPGMR_LRW] : size (in real words) of real workspace *
|
||||
* vectors and small matrices used by this *
|
||||
* solver. *
|
||||
* *
|
||||
* iopt[SPGMR_LIW] : size (in integer words) of integer *
|
||||
* workspace vectors used by this solver. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
enum { SPGMR_NPE = CVODE_IOPT_SIZE,
|
||||
SPGMR_NLI, SPGMR_NPS, SPGMR_NCFL, SPGMR_LRW, SPGMR_LIW };
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* CVSPGMR solver constants *
|
||||
*----------------------------------------------------------------*
|
||||
* CVSPGMR_MAXL : default value for the maximum Krylov *
|
||||
* dimension is MIN(N, CVSPGMR_MAXL) *
|
||||
* *
|
||||
* CVSPGMR_MSBPRE : maximum number of steps between *
|
||||
* preconditioner evaluations *
|
||||
* *
|
||||
* CVSPGMR_DGMAX : maximum change in gamma between *
|
||||
* preconditioner evaluations *
|
||||
* *
|
||||
* CVSPGMR_DELT : default value for factor by which the *
|
||||
* tolerance on the nonlinear iteration is *
|
||||
* multiplied to get a tolerance on the linear *
|
||||
* iteration *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#define CVSPGMR_MAXL 5
|
||||
|
||||
#define CVSPGMR_MSBPRE 50
|
||||
|
||||
#define CVSPGMR_DGMAX RCONST(0.2)
|
||||
|
||||
#define CVSPGMR_DELT RCONST(0.05)
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Type : CVSpgmrPrecondFn *
|
||||
*----------------------------------------------------------------*
|
||||
* The user-supplied preconditioner setup function Precond and *
|
||||
* the user-supplied preconditioner solve function PSolve *
|
||||
* together must define left and right preconditoner matrices *
|
||||
* P1 and P2 (either of which may be trivial), such that the *
|
||||
* product P1*P2 is an approximation to the Newton matrix *
|
||||
* M = I - gamma*J. Here J is the system Jacobian J = df/dy, *
|
||||
* and gamma is a scalar proportional to the integration step *
|
||||
* size h. The solution of systems P z = r, with P = P1 or P2, *
|
||||
* is to be carried out by the PSolve function, and Precond is *
|
||||
* to do any necessary setup operations. *
|
||||
* *
|
||||
* The user-supplied preconditioner setup function Precond *
|
||||
* is to evaluate and preprocess any Jacobian-related data *
|
||||
* needed by the preconditioner solve function PSolve. *
|
||||
* This might include forming a crude approximate Jacobian, *
|
||||
* and performing an LU factorization on the resulting *
|
||||
* approximation to M. This function will not be called in *
|
||||
* advance of every call to PSolve, but instead will be called *
|
||||
* only as often as necessary to achieve convergence within the *
|
||||
* Newton iteration in CVODE. If the PSolve function needs no *
|
||||
* preparation, the Precond function can be NULL. *
|
||||
* *
|
||||
* For greater efficiency, the Precond function may save *
|
||||
* Jacobian-related data and reuse it, rather than generating it *
|
||||
* from scratch. In this case, it should use the input flag jok *
|
||||
* to decide whether to recompute the data, and set the output *
|
||||
* flag *jcurPtr accordingly. *
|
||||
* *
|
||||
* Each call to the Precond function is preceded by a call to *
|
||||
* the RhsFn f with the same (t,y) arguments. Thus the Precond *
|
||||
* function can use any auxiliary data that is computed and *
|
||||
* saved by the f function and made accessible to Precond. *
|
||||
* *
|
||||
* The error weight vector ewt, step size h, and unit roundoff *
|
||||
* uround are provided to the Precond function for possible use *
|
||||
* in approximating Jacobian data, e.g. by difference quotients. *
|
||||
* *
|
||||
* A function Precond must have the prototype given below. *
|
||||
* Its parameters are as follows: *
|
||||
* *
|
||||
* N is the length of all vector arguments. *
|
||||
* *
|
||||
* t is the current value of the independent variable. *
|
||||
* *
|
||||
* y is the current value of the dependent variable vector, *
|
||||
* namely the predicted value of y(t). *
|
||||
* *
|
||||
* fy is the vector f(t,y). *
|
||||
* *
|
||||
* jok is an input flag indicating whether Jacobian-related *
|
||||
* data needs to be recomputed, as follows: *
|
||||
* jok == FALSE means recompute Jacobian-related data *
|
||||
* from scratch. *
|
||||
* jok == TRUE means that Jacobian data, if saved from *
|
||||
* the previous Precond call, can be reused *
|
||||
* (with the current value of gamma). *
|
||||
* A Precond call with jok == TRUE can only occur after *
|
||||
* a call with jok == FALSE. *
|
||||
* *
|
||||
* jcurPtr is a pointer to an output integer flag which is *
|
||||
* to be set by Precond as follows: *
|
||||
* Set *jcurPtr = TRUE if Jacobian data was recomputed. *
|
||||
* Set *jcurPtr = FALSE if Jacobian data was not *
|
||||
* recomputed, but saved data was reused. *
|
||||
* *
|
||||
* gamma is the scalar appearing in the Newton matrix. *
|
||||
* *
|
||||
* ewt is the error weight vector. *
|
||||
* *
|
||||
* h is a tentative step size in t. *
|
||||
* *
|
||||
* uround is the machine unit roundoff. *
|
||||
* *
|
||||
* nfePtr is a pointer to the memory location containing the *
|
||||
* CVODE problem data nfe = number of calls to f. *
|
||||
* The Precond routine should update this counter by *
|
||||
* adding on the number of f calls made in order to *
|
||||
* approximate the Jacobian, if any. For example, if *
|
||||
* the routine calls f a total of W times, then the *
|
||||
* update is *nfePtr += W. *
|
||||
* *
|
||||
* P_data is a pointer to user data - the same as the P_data *
|
||||
* parameter passed to CVSpgmr. *
|
||||
* *
|
||||
* vtemp1, vtemp2, and vtemp3 are pointers to memory allocated *
|
||||
* for vectors of length N which can be used by *
|
||||
* CVSpgmrPrecondFn as temporary storage or work space. *
|
||||
* *
|
||||
* *
|
||||
* Returned value: *
|
||||
* The value to be returned by the Precond function is a flag *
|
||||
* indicating whether it was successful. This value should be *
|
||||
* 0 if successful, *
|
||||
* > 0 for a recoverable error (step will be retried), *
|
||||
* < 0 for an unrecoverable error (integration is halted). *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
typedef int (*CVSpgmrPrecondFn)(integer N, real t, N_Vector y, N_Vector fy,
|
||||
boole jok, boole *jcurPtr, real gamma,
|
||||
N_Vector ewt, real h, real uround,
|
||||
long int *nfePtr, void *P_data,
|
||||
N_Vector vtemp1, N_Vector vtemp2,
|
||||
N_Vector vtemp3);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Type : CVSpgmrPSolveFn *
|
||||
*----------------------------------------------------------------*
|
||||
* The user-supplied preconditioner solve function PSolve *
|
||||
* is to solve a linear system P z = r in which the matrix P is *
|
||||
* one of the preconditioner matrices P1 or P2, depending on the *
|
||||
* type of preconditioning chosen. *
|
||||
* *
|
||||
* A function PSolve must have the prototype given below. *
|
||||
* Its parameters are as follows: *
|
||||
* *
|
||||
* N is the length of all vector arguments. *
|
||||
* *
|
||||
* t is the current value of the independent variable. *
|
||||
* *
|
||||
* y is the current value of the dependent variable vector. *
|
||||
* *
|
||||
* fy is the vector f(t,y). *
|
||||
* *
|
||||
* vtemp is a pointer to memory allocated for a vector of *
|
||||
* length N which can be used by PSolve for work space. *
|
||||
* *
|
||||
* gamma is the scalar appearing in the Newton matrix. *
|
||||
* *
|
||||
* ewt is the error weight vector (input). See delta below. *
|
||||
* *
|
||||
* delta is an input tolerance for use by PSolve if it uses *
|
||||
* an iterative method in its solution. In that case, *
|
||||
* the residual vector Res = r - P z of the system *
|
||||
* should be made less than delta in weighted L2 norm, *
|
||||
* i.e., sqrt [ Sum (Res[i]*ewt[i])^2 ] < delta . *
|
||||
* *
|
||||
* nfePtr is a pointer to the memory location containing the *
|
||||
* CVODE problem data nfe = number of calls to f. The *
|
||||
* PSolve routine should update this counter by adding *
|
||||
* on the number of f calls made in order to carry out *
|
||||
* the solution, if any. For example, if the routine *
|
||||
* calls f a total of W times, then the update is *
|
||||
* *nfePtr += W. *
|
||||
* *
|
||||
* r is the right-hand side vector of the linear system. *
|
||||
* *
|
||||
* lr is an input flag indicating whether PSolve is to use *
|
||||
* the left preconditioner P1 or right preconditioner *
|
||||
* P2: lr = 1 means use P1, and lr = 2 means use P2. *
|
||||
* *
|
||||
* P_data is a pointer to user data - the same as the P_data *
|
||||
* parameter passed to CVSpgmr. *
|
||||
* *
|
||||
* z is the output vector computed by PSolve. *
|
||||
* *
|
||||
* Returned value: *
|
||||
* The value to be returned by the PSolve function is a flag *
|
||||
* indicating whether it was successful. This value should be *
|
||||
* 0 if successful, *
|
||||
* positive for a recoverable error (step will be retried), *
|
||||
* negative for an unrecoverable error (integration is halted). *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
typedef int (*CVSpgmrPSolveFn)(integer N, real t, N_Vector y, N_Vector fy,
|
||||
N_Vector vtemp, real gamma, N_Vector ewt,
|
||||
real delta, long int *nfePtr, N_Vector r,
|
||||
int lr, void *P_data, N_Vector z);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : CVSpgmr *
|
||||
*----------------------------------------------------------------*
|
||||
* A call to the CVSpgmr function links the main CVODE integrator *
|
||||
* with the CVSPGMR linear solver. *
|
||||
* *
|
||||
* cvode_mem is the pointer to CVODE memory returned by *
|
||||
* CVodeMalloc. *
|
||||
* *
|
||||
* pretype is the type of user preconditioning to be done. *
|
||||
* This must be one of the four enumeration constants *
|
||||
* NONE, LEFT, RIGHT, or BOTH defined in iterativ.h. *
|
||||
* These correspond to no preconditioning, *
|
||||
* left preconditioning only, right preconditioning *
|
||||
* only, and both left and right preconditioning, *
|
||||
* respectively. *
|
||||
* *
|
||||
* gstype is the type of Gram-Schmidt orthogonalization to be *
|
||||
* used. This must be one of the two enumeration *
|
||||
* constants MODIFIED_GS or CLASSICAL_GS defined in *
|
||||
* iterativ.h. These correspond to using modified *
|
||||
* Gram-Schmidt and classical Gram-Schmidt, *
|
||||
* respectively. *
|
||||
* *
|
||||
* maxl is the maximum Krylov dimension. This is an *
|
||||
* optional input to the CVSPGMR solver. Pass 0 to *
|
||||
* use the default value MIN(N, CVSPGMR_MAXL=5). *
|
||||
* *
|
||||
* delt is the factor by which the tolerance on the *
|
||||
* nonlinear iteration is multiplied to get a *
|
||||
* tolerance on the linear iteration. This is an *
|
||||
* optional input to the CVSPGMR solver. Pass 0 to *
|
||||
* use the default value CVSPGMR_DELT = 0.05. *
|
||||
* *
|
||||
* precond is the user's preconditioner routine. It is used to *
|
||||
* evaluate and preprocess any Jacobian-related data *
|
||||
* needed by the psolve routine. See the *
|
||||
* documentation for the type CVSpgmrPrecondFn for *
|
||||
* full details. Pass NULL if no such setup of *
|
||||
* Jacobian data is required. A precond routine is *
|
||||
* NOT required for any of the four possible values *
|
||||
* of pretype. *
|
||||
* *
|
||||
* psolve is the user's preconditioner solve routine. It is *
|
||||
* used to solve Pz=r, where P is a preconditioner *
|
||||
* matrix. See the documentation for the type *
|
||||
* CVSpgmrPSolveFn for full details. The only case *
|
||||
* in which psolve is allowed to be NULL is when *
|
||||
* pretype is NONE. A valid psolve function must be *
|
||||
* supplied when any preconditioning is to be done. *
|
||||
* *
|
||||
* P_data is a pointer to user preconditioner data. This *
|
||||
* pointer is passed to precond and psolve every time *
|
||||
* these routines are called. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void CVSpgmr(void *cvode_mem, int pretype, int gstype, int maxl, real delt,
|
||||
CVSpgmrPrecondFn precond, CVSpgmrPSolveFn psolve, void *P_data);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,494 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : dense.h *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 6 May 1998 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the header file for a generic DENSE linear solver *
|
||||
* package. There are two sets of dense solver routines listed in *
|
||||
* this file: one set uses type DenseMat defined below and the *
|
||||
* other set uses the type real ** for dense matrix arguments. *
|
||||
* The two sets of dense solver routines make it easy to work *
|
||||
* with two types of dense matrices: *
|
||||
* *
|
||||
* (1) The DenseMat type is intended for use with large dense *
|
||||
* matrices whose elements/columns may be stored in *
|
||||
* non-contiguous memory locations or even distributed into *
|
||||
* different processor memories. This type may be modified to *
|
||||
* include such distribution information. If this is done, *
|
||||
* then all the routines that use DenseMat must be modified *
|
||||
* to reflect the new data structure. *
|
||||
* *
|
||||
* (2) The set of routines that use real ** (and NOT the DenseMat *
|
||||
* type) is intended for use with small matrices which can *
|
||||
* easily be allocated within a contiguous block of memory *
|
||||
* on a single processor. *
|
||||
* *
|
||||
* Routines that work with the type DenseMat begin with "Dense". *
|
||||
* The DenseAllocMat function allocates a dense matrix for use in *
|
||||
* the other DenseMat routines listed in this file. Matrix *
|
||||
* storage details are given in the documentation for the type *
|
||||
* DenseMat. The DenseAllocPiv function allocates memory for *
|
||||
* pivot information. The storage allocated by DenseAllocMat and *
|
||||
* DenseAllocPiv is deallocated by the routines DenseFreeMat and *
|
||||
* DenseFreePiv, respectively. The DenseFactor and DenseBacksolve *
|
||||
* routines perform the actual solution of a dense linear system. *
|
||||
* Note that the DenseBacksolve routine has a parameter b of type *
|
||||
* N_Vector. The current implementation makes use of a machine *
|
||||
* environment-specific macro (N_VDATA) which may not exist for *
|
||||
* other implementations of the type N_Vector. Thus, the *
|
||||
* implementation of DenseBacksolve may need to change if the *
|
||||
* type N_Vector is changed. *
|
||||
* *
|
||||
* Routines that work with real ** begin with "den" (except for *
|
||||
* the factor and solve routines which are called gefa and gesl, *
|
||||
* respectively). The underlying matrix storage is described in *
|
||||
* the documentation for denalloc. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#ifdef __cplusplus /* wrapper to enable C++ usage */
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifndef _dense_h
|
||||
#define _dense_h
|
||||
|
||||
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Type: DenseMat *
|
||||
*----------------------------------------------------------------*
|
||||
* The type DenseMat is defined to be a pointer to a structure *
|
||||
* with a size and a data field. The size field indicates the *
|
||||
* number of columns (== number of rows) of a dense matrix, while *
|
||||
* the data field is a two dimensional array used for component *
|
||||
* storage. The elements of a dense matrix are stored columnwise *
|
||||
* (i.e columns are stored one on top of the other in memory). If *
|
||||
* A is of type DenseMat, then the (i,j)th element of A (with *
|
||||
* 0 <= i,j <= size-1) is given by the expression (A->data)[j][i] *
|
||||
* or by the expression (A->data)[0][j*n+i]. The macros below *
|
||||
* allow a user to access efficiently individual matrix *
|
||||
* elements without writing out explicit data structure *
|
||||
* references and without knowing too much about the underlying *
|
||||
* element storage. The only storage assumption needed is that *
|
||||
* elements are stored columnwise and that a pointer to the jth *
|
||||
* column of elements can be obtained via the DENSE_COL macro. *
|
||||
* Users should use these macros whenever possible. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
typedef struct {
|
||||
integer size;
|
||||
real **data;
|
||||
} *DenseMat;
|
||||
|
||||
|
||||
/* DenseMat accessor macros */
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Macro : DENSE_ELEM *
|
||||
* Usage : DENSE_ELEM(A,i,j) = a_ij; OR *
|
||||
* a_ij = DENSE_ELEM(A,i,j); *
|
||||
*----------------------------------------------------------------*
|
||||
* DENSE_ELEM(A,i,j) references the (i,j)th element of the N by N *
|
||||
* DenseMat A, 0 <= i,j <= N-1. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#define DENSE_ELEM(A,i,j) ((A->data)[j][i])
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Macro : DENSE_COL *
|
||||
* Usage : col_j = DENSE_COL(A,j); *
|
||||
*----------------------------------------------------------------*
|
||||
* DENSE_COL(A,j) references the jth column of the N by N *
|
||||
* DenseMat A, 0 <= j <= N-1. The type of the expression *
|
||||
* DENSE_COL(A,j) is real *. After the assignment in the usage *
|
||||
* above, col_j may be treated as an array indexed from 0 to N-1. *
|
||||
* The (i,j)th element of A is referenced by col_j[i]. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#define DENSE_COL(A,j) ((A->data)[j])
|
||||
|
||||
|
||||
/* Functions that use the DenseMat representation for a dense matrix */
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : DenseAllocMat *
|
||||
* Usage : A = DenseAllocMat(N); *
|
||||
* if (A == NULL) ... memory request failed *
|
||||
*----------------------------------------------------------------*
|
||||
* DenseAllocMat allocates memory for an N by N dense matrix and *
|
||||
* returns the storage allocated (type DenseMat). DenseAllocMat *
|
||||
* returns NULL if the request for matrix storage cannot be *
|
||||
* satisfied. See the above documentation for the type DenseMat *
|
||||
* for matrix storage details. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
DenseMat DenseAllocMat(integer N);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : DenseAllocPiv *
|
||||
* Usage : p = DenseAllocPiv(N); *
|
||||
* if (p == NULL) ... memory request failed *
|
||||
*----------------------------------------------------------------*
|
||||
* DenseAllocPiv allocates memory for pivot information to be *
|
||||
* filled in by the DenseFactor routine during the factorization *
|
||||
* of an N by N dense matrix. The underlying type for pivot *
|
||||
* information is an array of N integers and this routine returns *
|
||||
* the pointer to the memory it allocates. If the request for *
|
||||
* pivot storage cannot be satisfied, DenseAllocPiv returns NULL. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
integer *DenseAllocPiv(integer N);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : DenseFactor *
|
||||
* Usage : ier = DenseFactor(A, p); *
|
||||
* if (ier != 0) ... A is singular *
|
||||
*----------------------------------------------------------------*
|
||||
* DenseFactor performs the LU factorization of the N by N dense *
|
||||
* matrix A. This is done using standard Gaussian elimination *
|
||||
* with partial pivoting. *
|
||||
* *
|
||||
* A successful LU factorization leaves the matrix A and the *
|
||||
* pivot array p with the following information: *
|
||||
* *
|
||||
* (1) p[k] contains the row number of the pivot element chosen *
|
||||
* at the beginning of elimination step k, k=0, 1, ..., N-1. *
|
||||
* *
|
||||
* (2) If the unique LU factorization of A is given by PA = LU, *
|
||||
* where P is a permutation matrix, L is a lower triangular *
|
||||
* matrix with all 1's on the diagonal, and U is an upper *
|
||||
* triangular matrix, then the upper triangular part of A *
|
||||
* (including its diagonal) contains U and the strictly lower *
|
||||
* triangular part of A contains the multipliers, I-L. *
|
||||
* *
|
||||
* DenseFactor returns 0 if successful. Otherwise it encountered *
|
||||
* a zero diagonal element during the factorization. In this case *
|
||||
* it returns the column index (numbered from one) at which *
|
||||
* it encountered the zero. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
integer DenseFactor(DenseMat A, integer *p);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : DenseBacksolve *
|
||||
* Usage : DenseBacksolve(A, p, b); *
|
||||
*----------------------------------------------------------------*
|
||||
* DenseBacksolve solves the N-dimensional system A x = b using *
|
||||
* the LU factorization in A and the pivot information in p *
|
||||
* computed in DenseFactor. The solution x is returned in b. This *
|
||||
* routine cannot fail if the corresponding call to DenseFactor *
|
||||
* did not fail. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void DenseBacksolve(DenseMat A, integer *p, N_Vector b);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : DenseZero *
|
||||
* Usage : DenseZero(A); *
|
||||
*----------------------------------------------------------------*
|
||||
* DenseZero sets all the elements of the N by N matrix A to 0.0. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void DenseZero(DenseMat A);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : DenseCopy *
|
||||
* Usage : DenseCopy(A, B); *
|
||||
*----------------------------------------------------------------*
|
||||
* DenseCopy copies the contents of the N by N matrix A into the *
|
||||
* N by N matrix B. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void DenseCopy(DenseMat A, DenseMat B);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function: DenseScale *
|
||||
* Usage : DenseScale(c, A); *
|
||||
*----------------------------------------------------------------*
|
||||
* DenseScale scales the elements of the N by N matrix A by the *
|
||||
* constant c and stores the result back in A. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void DenseScale(real c, DenseMat A);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : DenseAddI *
|
||||
* Usage : DenseAddI(A); *
|
||||
*----------------------------------------------------------------*
|
||||
* DenseAddI adds the identity matrix to A and stores the result *
|
||||
* back in A. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void DenseAddI(DenseMat A);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : DenseFreeMat *
|
||||
* Usage : DenseFreeMat(A); *
|
||||
*----------------------------------------------------------------*
|
||||
* DenseFreeMat frees the memory allocated by DenseAllocMat for *
|
||||
* the N by N matrix A. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void DenseFreeMat(DenseMat A);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : DenseFreePiv *
|
||||
* Usage : DenseFreePiv(p); *
|
||||
*----------------------------------------------------------------*
|
||||
* DenseFreePiv frees the memory allocated by DenseAllocPiv for *
|
||||
* the pivot information array p. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void DenseFreePiv(integer *p);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : DensePrint *
|
||||
* Usage : DensePrint(A); *
|
||||
*----------------------------------------------------------------*
|
||||
* This routine prints the N by N dense matrix A to standard *
|
||||
* output as it would normally appear on paper. It is intended *
|
||||
* as a debugging tool with small values of N. The elements are *
|
||||
* printed using the %g option. A blank line is printed before *
|
||||
* and after the matrix. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void DensePrint(DenseMat A);
|
||||
|
||||
|
||||
|
||||
/* Functions that use the real ** representation for a dense matrix */
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : denalloc *
|
||||
* Usage : real **a; *
|
||||
* a = denalloc(n); *
|
||||
* if (a == NULL) ... memory request failed *
|
||||
*----------------------------------------------------------------*
|
||||
* denalloc(n) allocates storage for an n by n dense matrix. It *
|
||||
* returns a pointer to the newly allocated storage if *
|
||||
* successful. If the memory request cannot be satisfied, then *
|
||||
* denalloc returns NULL. The underlying type of the dense matrix *
|
||||
* returned is real **. If we allocate a dense matrix real **a by *
|
||||
* a = denalloc(n), then a[j][i] references the (i,j)th element *
|
||||
* of the matrix a, 0 <= i,j <= n-1, and a[j] is a pointer to the *
|
||||
* first element in the jth column of a. The location a[0] *
|
||||
* contains a pointer to n^2 contiguous locations which contain *
|
||||
* the elements of a. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
real **denalloc(integer n);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : denallocpiv *
|
||||
* Usage : integer *pivot; *
|
||||
* pivot = denallocpiv(n); *
|
||||
* if (pivot == NULL) ... memory request failed *
|
||||
*----------------------------------------------------------------*
|
||||
* denallocpiv(n) allocates an array of n integers. It returns a *
|
||||
* pointer to the first element in the array if successful. It *
|
||||
* returns NULL if the memory request could not be satisfied. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
integer *denallocpiv(integer n);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : gefa *
|
||||
* Usage : integer ier; *
|
||||
* ier = gefa(a,n,p); *
|
||||
* if (ier > 0) ... zero element encountered during *
|
||||
* the factorization *
|
||||
*----------------------------------------------------------------*
|
||||
* gefa(a,n,p) factors the n by n dense matrix a. It overwrites *
|
||||
* the elements of a with its LU factors and keeps track of the *
|
||||
* pivot rows chosen in the pivot array p. *
|
||||
* *
|
||||
* A successful LU factorization leaves the matrix a and the *
|
||||
* pivot array p with the following information: *
|
||||
* *
|
||||
* (1) p[k] contains the row number of the pivot element chosen *
|
||||
* at the beginning of elimination step k, k=0, 1, ..., n-1. *
|
||||
* *
|
||||
* (2) If the unique LU factorization of a is given by Pa = LU, *
|
||||
* where P is a permutation matrix, L is a lower triangular *
|
||||
* matrix with all 1's on the diagonal, and U is an upper *
|
||||
* triangular matrix, then the upper triangular part of a *
|
||||
* (including its diagonal) contains U and the strictly lower *
|
||||
* triangular part of a contains the multipliers, I-L. *
|
||||
* *
|
||||
* gefa returns 0 if successful. Otherwise it encountered a zero *
|
||||
* diagonal element during the factorization. In this case it *
|
||||
* returns the column index (numbered from one) at which it *
|
||||
* encountered the zero. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
integer gefa(real **a, integer n, integer *p);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : gesl *
|
||||
* Usage : real *b; *
|
||||
* ier = gefa(a,n,p); *
|
||||
* if (ier == 0) gesl(a,n,p,b); *
|
||||
*----------------------------------------------------------------*
|
||||
* gesl(a,n,p,b) solves the n by n linear system ax = b. It *
|
||||
* assumes that a has been LU factored and the pivot array p has *
|
||||
* been set by a successful call to gefa(a,n,p). The solution x *
|
||||
* is written into the b array. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void gesl(real **a, integer n, integer *p, real *b);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : denzero *
|
||||
* Usage : denzero(a,n); *
|
||||
*----------------------------------------------------------------*
|
||||
* denzero(a,n) sets all the elements of the n by n dense matrix *
|
||||
* a to be 0.0. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void denzero(real **a, integer n);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : dencopy *
|
||||
* Usage : dencopy(a,b,n); *
|
||||
*----------------------------------------------------------------*
|
||||
* dencopy(a,b,n) copies the n by n dense matrix a into the *
|
||||
* n by n dense matrix b. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void dencopy(real **a, real **b, integer n);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : denscale *
|
||||
* Usage : denscale(c,a,n); *
|
||||
*----------------------------------------------------------------*
|
||||
* denscale(c,a,n) scales every element in the n by n dense *
|
||||
* matrix a by c. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void denscale(real c, real **a, integer n);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : denaddI *
|
||||
* Usage : denaddI(a,n); *
|
||||
*----------------------------------------------------------------*
|
||||
* denaddI(a,n) increments the n by n dense matrix a by the *
|
||||
* identity matrix. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void denaddI(real **a, integer n);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : denfreepiv *
|
||||
* Usage : denfreepiv(p); *
|
||||
*----------------------------------------------------------------*
|
||||
* denfreepiv(p) frees the pivot array p allocated by *
|
||||
* denallocpiv. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void denfreepiv(integer *p);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : denfree *
|
||||
* Usage : denfree(a); *
|
||||
*----------------------------------------------------------------*
|
||||
* denfree(a) frees the dense matrix a allocated by denalloc. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void denfree(real **a);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : denprint *
|
||||
* Usage : denprint(a,n); *
|
||||
*----------------------------------------------------------------*
|
||||
* denprint(a,n) prints the n by n dense matrix a to standard *
|
||||
* output as it would normally appear on paper. It is intended as *
|
||||
* a debugging tool with small values of n. The elements are *
|
||||
* printed using the %g option. A blank line is printed before *
|
||||
* and after the matrix. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
void denprint(real **a, integer n);
|
||||
|
||||
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,243 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : iterativ.h *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 4 May 1998 *
|
||||
*----------------------------------------------------------------*
|
||||
* This header file contains declarations intended for use by *
|
||||
* generic iterative solvers of Ax = b. The enumeration gives *
|
||||
* symbolic names for the type of preconditioning to be used. *
|
||||
* The function type declarations give the prototypes for the *
|
||||
* functions to be called within an iterative linear solver, that *
|
||||
* are responsible for *
|
||||
* multiplying A by a given vector v (ATimesFn), and *
|
||||
* solving the preconditioner equation Pz = r (PSolveFn). *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#ifdef __cplusplus /* wrapper to enable C++ usage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _iterativ_h
|
||||
#define _iterativ_h
|
||||
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* enum : types of preconditioning *
|
||||
*----------------------------------------------------------------*
|
||||
* NONE : The iterative linear solver should not use *
|
||||
* preconditioning. *
|
||||
* *
|
||||
* LEFT : The iterative linear solver uses preconditioning on *
|
||||
* the left only. *
|
||||
* *
|
||||
* RIGHT : The iterative linear solver uses preconditioning on *
|
||||
* the right only. *
|
||||
* *
|
||||
* BOTH : The iterative linear solver uses preconditioning on *
|
||||
* both the left and the right. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
enum { NONE, LEFT, RIGHT, BOTH };
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* enum : types of Gram-Schmidt routines *
|
||||
*----------------------------------------------------------------*
|
||||
* MODIFIED_GS : The iterative solver uses the modified *
|
||||
* Gram-Schmidt routine ModifiedGS listed in this *
|
||||
* file. *
|
||||
* *
|
||||
* CLASSICAL_GS : The iterative solver uses the classical *
|
||||
* Gram-Schmidt routine ClassicalGS listed in this *
|
||||
* file. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
enum { MODIFIED_GS, CLASSICAL_GS };
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Type: ATimesFn *
|
||||
*----------------------------------------------------------------*
|
||||
* An ATimesFn multiplies Av and stores the result in z. The *
|
||||
* caller is responsible for allocating memory for the z vector. *
|
||||
* The parameter A_data is a pointer to any information about A *
|
||||
* which the function needs in order to do its job. The vector v *
|
||||
* is unchanged. An ATimesFn returns 0 if successful and a *
|
||||
* non-zero value if unsuccessful. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
typedef int (*ATimesFn)(void *A_data, N_Vector v, N_Vector z);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Type: PSolveFn *
|
||||
*----------------------------------------------------------------*
|
||||
* A PSolveFn solves the preconditioner equation Pz = r for the *
|
||||
* vector z. The caller is responsible for allocating memory for *
|
||||
* the z vector. The parameter P_data is a pointer to any *
|
||||
* information about P which the function needs in order to do *
|
||||
* its job. The parameter lr is input, and indicates whether P *
|
||||
* is to be taken as the left preconditioner or the right *
|
||||
* preconditioner: lr = 1 for left and lr = 2 for right. *
|
||||
* If preconditioning is on one side only, lr can be ignored. *
|
||||
* The vector r is unchanged. *
|
||||
* A PSolveFn returns 0 if successful and a non-zero value if *
|
||||
* unsuccessful. On a failure, a negative return value indicates *
|
||||
* an unrecoverable condition, while a positive value indicates *
|
||||
* a recoverable one, in which the calling routine may reattempt *
|
||||
* the solution after updating preconditioner data. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
typedef int (*PSolveFn)(void *P_data, N_Vector r, N_Vector z, int lr);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function: ModifiedGS *
|
||||
*----------------------------------------------------------------*
|
||||
* ModifiedGS performs a modified Gram-Schmidt orthogonalization *
|
||||
* of the N_Vector v[k] against the p unit N_Vectors at *
|
||||
* v[k-1], v[k-2], ..., v[k-p]. *
|
||||
* *
|
||||
* v is an array of (k+1) N_Vectors v[i], i=0, 1, ..., k. *
|
||||
* v[k-1], v[k-2], ..., v[k-p] are assumed to have L2-norm *
|
||||
* equal to 1. *
|
||||
* *
|
||||
* h is the output k by k Hessenberg matrix of inner products. *
|
||||
* This matrix must be allocated row-wise so that the (i,j)th *
|
||||
* entry is h[i][j]. The inner products (v[i],v[k]), *
|
||||
* i=i0, i0+1, ..., k-1, are stored at h[i][k-1]. Here *
|
||||
* i0=MAX(0,k-p). *
|
||||
* *
|
||||
* k is the index of the vector in the v array that needs to be *
|
||||
* orthogonalized against previous vectors in the v array. *
|
||||
* *
|
||||
* p is the number of previous vectors in the v array against *
|
||||
* which v[k] is to be orthogonalized. *
|
||||
* *
|
||||
* new_vk_norm is a pointer to memory allocated by the caller to *
|
||||
* hold the Euclidean norm of the orthogonalized vector v[k]. *
|
||||
* *
|
||||
* If (k-p) < 0, then ModifiedGS uses p=k. The orthogonalized *
|
||||
* v[k] is NOT normalized and is stored over the old v[k]. Once *
|
||||
* the orthogonalization has been performed, the Euclidean norm *
|
||||
* of v[k] is stored in (*new_vk_norm). *
|
||||
* *
|
||||
* ModifiedGS returns 0 to indicate success. It cannot fail. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
int ModifiedGS(N_Vector *v, real **h, int k, int p, real *new_vk_norm);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function: ClassicalGS *
|
||||
*----------------------------------------------------------------*
|
||||
* ClassicalGS performs a classical Gram-Schmidt *
|
||||
* orthogonalization of the N_Vector v[k] against the p unit *
|
||||
* N_Vectors at v[k-1], v[k-2], ..., v[k-p]. The parameters v, h, *
|
||||
* k, p, and new_vk_norm are as described in the documentation *
|
||||
* for ModifiedGS. *
|
||||
* *
|
||||
* temp is an N_Vector which can be used as workspace by the *
|
||||
* ClassicalGS routine. *
|
||||
* *
|
||||
* s is a length k array of reals which can be used as workspace *
|
||||
* by the ClassicalGS routine. *
|
||||
* *
|
||||
* ClassicalGS returns 0 to indicate success. It cannot fail. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
int ClassicalGS(N_Vector *v, real **h, int k, int p, real *new_vk_norm,
|
||||
N_Vector temp, real *s);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function: QRfact *
|
||||
*----------------------------------------------------------------*
|
||||
* QRfact performs a QR factorization of the Hessenberg matrix H. *
|
||||
* *
|
||||
* n is the problem size; the matrix H is (n+1) by n. *
|
||||
* *
|
||||
* h is the (n+1) by n Hessenberg matrix H to be factored. It is *
|
||||
* stored row-wise. *
|
||||
* *
|
||||
* q is an array of length 2*n containing the Givens rotations *
|
||||
* computed by this function. A Givens rotation has the form: *
|
||||
* | c -s | *
|
||||
* | s c |. *
|
||||
* The components of the Givens rotations are stored in q as *
|
||||
* (c, s, c, s, ..., c, s). *
|
||||
* *
|
||||
* job is a control flag. If job==0, then a new QR factorization *
|
||||
* is performed. If job!=0, then it is assumed that the first *
|
||||
* n-1 columns of h have already been factored and only the last *
|
||||
* column needs to be updated. *
|
||||
* *
|
||||
* QRfact returns 0 if successful. If a zero is encountered on *
|
||||
* the diagonal of the triangular factor R, then QRfact returns *
|
||||
* the equation number of the zero entry, where the equations are *
|
||||
* numbered from 1, not 0. If QRsol is subsequently called in *
|
||||
* this situation, it will return an error because it could not *
|
||||
* divide by the zero diagonal entry. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
int QRfact(int n, real **h, real *q, int job);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function: QRsol *
|
||||
*----------------------------------------------------------------*
|
||||
* QRsol solves the linear least squares problem *
|
||||
* *
|
||||
* min (b - H*x, b - H*x), x in R^n, *
|
||||
* *
|
||||
* where H is a Hessenberg matrix, and b is in R^(n+1). *
|
||||
* It uses the QR factors of H computed by QRfact. *
|
||||
* *
|
||||
* n is the problem size; the matrix H is (n+1) by n. *
|
||||
* *
|
||||
* h is a matrix (computed by QRfact) containing the upper *
|
||||
* triangular factor R of the original Hessenberg matrix H. *
|
||||
* *
|
||||
* q is an array of length 2*n (computed by QRfact) containing *
|
||||
* the Givens rotations used to factor H. *
|
||||
* *
|
||||
* b is the (n+1)-vector appearing in the least squares problem *
|
||||
* above. *
|
||||
* *
|
||||
* On return, b contains the solution x of the least squares *
|
||||
* problem, if QRsol was successful. *
|
||||
* *
|
||||
* QRsol returns a 0 if successful. Otherwise, a zero was *
|
||||
* encountered on the diagonal of the triangular factor R. *
|
||||
* In this case, QRsol returns the equation number (numbered *
|
||||
* from 1, not 0) of the zero entry. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
int QRsol(int n, real **h, real *q, real *b);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : llnlmath.h *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 4 May 1998 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the header file for a C math library. The routines *
|
||||
* listed here work with the type real as defined in llnltyps.h. *
|
||||
* To do single precision floating point arithmetic, set the type *
|
||||
* real to be float. To do double precision arithmetic, set the *
|
||||
* type real to be double. The default implementations for *
|
||||
* RPowerR and RSqrt call standard math library functions which *
|
||||
* do double precision arithmetic. If this is unacceptable when *
|
||||
* real is float, then the user should re-implement these two *
|
||||
* routines by calling single precision routines available on *
|
||||
* his/her machine. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#ifdef __cplusplus /* wrapper to enable C++ usage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _llnlmath_h
|
||||
#define _llnlmath_h
|
||||
|
||||
#include "llnltyps.h"
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Macros : MIN, MAX, ABS, SQR *
|
||||
*----------------------------------------------------------------*
|
||||
* MIN(A, B) returns the minimum of A and B. *
|
||||
* *
|
||||
* MAX(A, B) returns the maximum of A and B. *
|
||||
* *
|
||||
* ABS(A) returns the absolute value of A. *
|
||||
* *
|
||||
* SQR(A) returns the square of A. *
|
||||
* *
|
||||
******************************************************************/
|
||||
#ifndef MIN
|
||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||
#endif
|
||||
|
||||
#ifndef ABS
|
||||
#define ABS(A) ((A < 0) ? -(A) : (A))
|
||||
#endif
|
||||
|
||||
#ifndef SQR
|
||||
#define SQR(A) ((A) * (A))
|
||||
#endif
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : UnitRoundoff *
|
||||
* Usage : real uround; *
|
||||
* uround = UnitRoundoff(); *
|
||||
*----------------------------------------------------------------*
|
||||
* UnitRoundoff returns the unit roundoff u for real floating *
|
||||
* point arithmetic, where u is defined to be the smallest *
|
||||
* positive real such that 1.0 + u != 1.0. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
real UnitRoundoff(void);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : RPowerI *
|
||||
* Usage : int exponent; *
|
||||
* real base, ans; *
|
||||
* ans = RPowerI(base,exponent); *
|
||||
*----------------------------------------------------------------*
|
||||
* RPowerI returns the value base^exponent, where base is a real *
|
||||
* and exponent is an int. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
real RPowerI(real base, int exponent);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : RPowerR *
|
||||
* Usage : real base, exponent, ans; *
|
||||
* ans = RPowerR(base,exponent); *
|
||||
*----------------------------------------------------------------*
|
||||
* RPowerR returns the value base^exponent, where both base and *
|
||||
* exponent are reals. If base < 0.0, then RPowerR returns 0.0. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
real RPowerR(real base, real exponent);
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Function : RSqrt *
|
||||
* Usage : real sqrt_x; *
|
||||
* sqrt_x = RSqrt(x); *
|
||||
*----------------------------------------------------------------*
|
||||
* RSqrt(x) returns the square root of x. If x < 0.0, then RSqrt *
|
||||
* returns 0.0. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
real RSqrt(real x);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : llnltyps.h *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 4 May 1998 *
|
||||
*----------------------------------------------------------------*
|
||||
* This header file exports three types: real, integer, and boole *
|
||||
* (short for boolean), as well as the constants TRUE and FALSE. *
|
||||
* *
|
||||
* Users should #include "llnltyps.h" in any file that should *
|
||||
* be easily modifiable to work with different real or integer *
|
||||
* types and use the exported names real and integer within such *
|
||||
* a file. The types for real and integer below have been set to *
|
||||
* double and int, respectively. A user should modify these *
|
||||
* type declarations as he/she sees fit. For example, if a user *
|
||||
* wants the work with type float because double precision *
|
||||
* floating point arithmetic is too expensive on the user's *
|
||||
* machine, then the definition below should be changed to: *
|
||||
* *
|
||||
* typedef float real; *
|
||||
* *
|
||||
* Similarly, if a user needs to work with extremely large *
|
||||
* integers (see the system header file <limits.h> for the limits *
|
||||
* on type int and long int on your machine), then the user *
|
||||
* should change the definition below to: *
|
||||
* *
|
||||
* typedef long int integer; *
|
||||
* *
|
||||
* The constants LLNL_FLOAT, LLNL_DOUBLE, LLNL_INT, LLNL_LONG *
|
||||
* indicate the underlying types for real and integer. *
|
||||
* They should be set as follows: *
|
||||
* *
|
||||
* (1) #define LLNL_FLOAT 1 *
|
||||
* #define LLNL_DOUBLE 0 (real is float) *
|
||||
* *
|
||||
* (2) #define LLNL_FLOAT 0 *
|
||||
* #define LLNL_DOUBLE 1 (real is double) *
|
||||
* *
|
||||
* (3) #define LLNL_INT 1 *
|
||||
* #define LLNL_LONG 0 (integer is int) *
|
||||
* *
|
||||
* (4) #define LLNL_INT 0 *
|
||||
* #define LLNL_LONG 1 (integer is long int) *
|
||||
* *
|
||||
* Thus the legal types for real are float and double, while *
|
||||
* the legal types for integer are int and long int. The macro *
|
||||
* RCONST gives a user a convenient way to define real *
|
||||
* constants. To use the real constant 1.0, for example, the *
|
||||
* user should write *
|
||||
* *
|
||||
* #define ONE RCONST(1.0) *
|
||||
* *
|
||||
* If real is double, then RCONST(1.0) expands to 1.0. If real is *
|
||||
* float, then RCONST(1.0) expands to 1.0F. There is never a *
|
||||
* need to explicitly cast 1.0 to (real). *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#ifdef __cplusplus /* wrapper to enable C++ usage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _llnltyps_h
|
||||
#define _llnltyps_h
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Types : real, integer *
|
||||
*----------------------------------------------------------------*
|
||||
* The types real and integer are currently set to double and *
|
||||
* int, respectively. See the documentation at the top for *
|
||||
* usage details and a description of associated constants and *
|
||||
* macros. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
typedef double real;
|
||||
//typedef long int integer;
|
||||
typedef int integer;
|
||||
|
||||
#define LLNL_FLOAT 0
|
||||
#define LLNL_DOUBLE 1
|
||||
|
||||
#define LLNL_INT 1
|
||||
#define LLNL_LONG 0
|
||||
|
||||
#if LLNL_FLOAT
|
||||
|
||||
#define RCONST(x) x##F
|
||||
|
||||
#elif LLNL_DOUBLE
|
||||
|
||||
#define RCONST(x) x
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Type : boole *
|
||||
* Constants : FALSE, TRUE *
|
||||
*----------------------------------------------------------------*
|
||||
* ANSI C does not have a built-in boolean type. Below is the *
|
||||
* definition for a new type boole. The advantage of using the *
|
||||
* name boole (instead of int) is an increase in code readability.*
|
||||
* It allows the programmer to make a distinction between int and *
|
||||
* boolean data. Variables of type boole are intended to have only*
|
||||
* the two values FALSE and TRUE which are defined below to be *
|
||||
* equal to 0 and 1, respectively. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#ifndef boole
|
||||
#define boole int
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,535 +0,0 @@
|
|||
/****************************************************************
|
||||
* *
|
||||
* File : nvector.h *
|
||||
* Programmers : Scott D. Cohen, Alan C. Hindmarsh, and *
|
||||
* : Allan G. Taylor, LLNL *
|
||||
* Version of : 17 December 1999 *
|
||||
*--------------------------------------------------------------*
|
||||
* *
|
||||
* This is the header file for a generic serial NVECTOR package.*
|
||||
* It exports the type N_Vector. *
|
||||
* *
|
||||
* Part I of this file contains declarations which are specific *
|
||||
* to the particular machine environment in which this version *
|
||||
* of the vector package is to be used. This includes the *
|
||||
* typedef for the type N_Vector, as well as accessor macros *
|
||||
* that allow the user to use efficiently the type N_Vector *
|
||||
* without making explicit references to its underlying *
|
||||
* representation. The underlying type of N_Vector will always *
|
||||
* be some pointer type. *
|
||||
* *
|
||||
* Part II of this file contains the prototypes for the vector *
|
||||
* kernels which operate on the type N_Vector. These prototypes *
|
||||
* are fixed for all implementations of the vector package. The *
|
||||
* definitions of the types real and integer are in the header *
|
||||
* file llnltyps.h and these may be changed according to the *
|
||||
* user's needs. The llnltyps.h file also contains the *
|
||||
* definition for the type boole (short for boolean) that is the*
|
||||
* return type for the routine N_VInvTest. *
|
||||
* *
|
||||
* Important Note: N_Vector arguments to arithmetic kernels *
|
||||
* need not be distinct. Thus, for example, the call *
|
||||
* N_VLinearSum(a,x,b,y,y); y <- ax+by *
|
||||
* is legal. *
|
||||
* *
|
||||
* This version of nvector.h is for the ordinary sequential *
|
||||
* machine environment. In the documentation given below, N is *
|
||||
* the length of all N_Vector parameters and x[i] denotes the *
|
||||
* ith component of the N_Vector x, where 0 <= i <= N-1. *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
|
||||
#ifdef __cplusplus /* wrapper to enable C++ usage */
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifndef nvector_h
|
||||
#define nvector_h
|
||||
|
||||
|
||||
#include "llnltyps.h"
|
||||
|
||||
|
||||
/* Part I: Machine Environment-Dependent Declarations */
|
||||
|
||||
|
||||
/* Environment: Sequential */
|
||||
|
||||
typedef struct {
|
||||
int dummy; /* dummy element */
|
||||
} *machEnvType; /* dummy machEnvType definition */
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Type: N_Vector *
|
||||
*-------------------------------------------------------------*
|
||||
* The type N_Vector is an abstract vector type. The fields of *
|
||||
* its concrete representation should not be accessed *
|
||||
* directly, but rather through the macros given below. *
|
||||
* *
|
||||
* A user may assume that the N components of an N_Vector *
|
||||
* are stored contiguously. A pointer to the first component *
|
||||
* can be obtained via the macro N_VDATA. *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
typedef struct {
|
||||
integer length;
|
||||
real *data;
|
||||
} *N_Vector;
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Macros: N_VMAKE, N_VDISPOSE, N_VDATA, N_VLENGTH, N_VIth *
|
||||
*-------------------------------------------------------------*
|
||||
* In the descriptions below, the following user *
|
||||
* declarations are assumed: *
|
||||
* *
|
||||
* N_Vector v; real *v_data, r; integer v_len, i; *
|
||||
* *
|
||||
* (1) N_VMAKE, N_VDISPOSE *
|
||||
* *
|
||||
* These companion routines are used to create and *
|
||||
* destroy an N_Vector with a component array v_data *
|
||||
* allocated by the user. *
|
||||
* *
|
||||
* The call N_VMAKE(v, v_data, v_len) makes v an *
|
||||
* N_Vector with component array v_data and length v_len. *
|
||||
* N_VMAKE stores the pointer v_data so that changes *
|
||||
* made by the user to the elements of v_data are *
|
||||
* simultaneously reflected in v. There is no copying of *
|
||||
* elements. *
|
||||
* *
|
||||
* The call N_VDISPOSE(v) frees all memory associated *
|
||||
* with v except for its component array. This memory was *
|
||||
* allocated by the user and, therefore, should be *
|
||||
* deallocated by the user. *
|
||||
* *
|
||||
* (2) N_VDATA, N_VLENGTH *
|
||||
* *
|
||||
* These routines give individual access to the parts of *
|
||||
* an N_Vector. *
|
||||
* *
|
||||
* The assignment v_data=N_VDATA(v) sets v_data to be *
|
||||
* a pointer to the first component of v. The assignment *
|
||||
* N_VDATA(v)=v_data sets the component array of v to *
|
||||
* be v_data by storing the pointer v_data. *
|
||||
* *
|
||||
* The assignment v_len=N_VLENGTH(v) sets v_len to be *
|
||||
* the length of v. The call N_VLENGTH(v)=len_v sets *
|
||||
* the length of v to be len_v. *
|
||||
* *
|
||||
* (3) N_VIth *
|
||||
* *
|
||||
* In the following description, the components of an *
|
||||
* N_Vector are numbered 0..N-1, where N is the length of *
|
||||
* v. *
|
||||
* *
|
||||
* The assignment r=N_VIth(v,i) sets r to be the value of *
|
||||
* the ith component of v. The assignment N_VIth(v,i)=r *
|
||||
* sets the value of the ith component of v to be r. *
|
||||
* *
|
||||
* Notes.. *
|
||||
* *
|
||||
* Users who use the macros (1) must #include<stdlib.h> *
|
||||
* since these macros expand to calls to malloc and free. *
|
||||
* *
|
||||
* When looping over the components of an N_Vector v, it is *
|
||||
* more efficient to first obtain the component array via *
|
||||
* v_data=N_VDATA(v) and then access v_data[i] within the *
|
||||
* loop than it is to use N_VIth(v,i) within the loop. *
|
||||
* *
|
||||
* N_VMAKE and N_VDISPOSE are similar to N_VNew and N_VFree. *
|
||||
* The difference is one of responsibility for component *
|
||||
* memory allocation and deallocation. N_VNew allocates memory *
|
||||
* for the N_Vector components and N_VFree frees the component *
|
||||
* memory allocated by N_VNew. For N_VMAKE and N_VDISPOSE, the *
|
||||
* component memory is allocated and freed by the user of *
|
||||
* this package. *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
#define N_VMAKE(v, v_data, v_len) v = (N_Vector) malloc(sizeof(*v)); \
|
||||
v->data = v_data; \
|
||||
v->length = v_len
|
||||
|
||||
#define N_VDISPOSE(v) free(v)
|
||||
|
||||
#define N_VDATA(v) (v->data)
|
||||
|
||||
#define N_VLENGTH(v) (v->length)
|
||||
|
||||
#define N_VIth(v,i) ((v->data)[i])
|
||||
|
||||
|
||||
/* Part II: N_Vector Kernel Prototypes (Machine Environment-Independent) */
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Memory Allocation and Deallocation: N_VNew, N_VFree *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VNew *
|
||||
* Usage : x = N_VNew(N, machEnv); *
|
||||
*-------------------------------------------------------------*
|
||||
* *
|
||||
* Returns a new N_Vector of length N. The parameter machEnv *
|
||||
* is a pointer to machine environment-specific information. *
|
||||
* It is ignored in the sequential machine environment and the *
|
||||
* user in this environment should simply pass NULL for this *
|
||||
* argument. If there is not enough memory for a new N_Vector, *
|
||||
* then N_VNew returns NULL. *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
N_Vector N_VNew(integer n, void *machEnv);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VFree *
|
||||
* Usage : N_VFree(x); *
|
||||
*-------------------------------------------------------------*
|
||||
* *
|
||||
* Frees the N_Vector x. It is illegal to use x after the call *
|
||||
* N_VFree(x). *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
void N_VFree(N_Vector x);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* N_Vector Arithmetic: N_VLinearSum, N_VConst, N_VProd, *
|
||||
* N_VDiv, N_VScale, N_VAbs, N_VInv, *
|
||||
* N_VAddConst *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VLinearSum *
|
||||
* Operation : z = a x + b y *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
void N_VLinearSum(real a, N_Vector x, real b, N_Vector y, N_Vector z);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VConst *
|
||||
* Operation : z[i] = c for i=0, 1, ..., N-1 *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
void N_VConst(real c, N_Vector z);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VProd *
|
||||
* Operation : z[i] = x[i] * y[i] for i=0, 1, ..., N-1 *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
void N_VProd(N_Vector x, N_Vector y, N_Vector z);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VDiv *
|
||||
* Operation : z[i] = x[i] / y[i] for i=0, 1, ..., N-1 *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
void N_VDiv(N_Vector x, N_Vector y, N_Vector z);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VScale *
|
||||
* Operation : z = c x *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
void N_VScale(real c, N_Vector x, N_Vector z);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VAbs *
|
||||
* Operation : z[i] = |x[i]|, for i=0, 1, ..., N-1 *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
void N_VAbs(N_Vector x, N_Vector z);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VInv *
|
||||
* Operation : z[i] = 1.0 / x[i] for i = 0, 1, ..., N-1 *
|
||||
*-------------------------------------------------------------*
|
||||
* *
|
||||
* This routine does not check for division by 0. It should be *
|
||||
* called only with an N_Vector x which is guaranteed to have *
|
||||
* all non-zero components. *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
void N_VInv(N_Vector x, N_Vector z);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VAddConst *
|
||||
* Operation : z[i] = x[i] + b for i = 0, 1, ..., N-1 *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
void N_VAddConst(N_Vector x, real b, N_Vector z);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* N_Vector Measures: N_VDotProd, N_VMaxNorm, VWrmsNorm, *
|
||||
* N_VMin, N_VWL2Norm, N_VL1Norm *
|
||||
* *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VDotProd *
|
||||
* Usage : dotprod = N_VDotProd(x, y); *
|
||||
*-------------------------------------------------------------*
|
||||
* *
|
||||
* Returns the value of the ordinary dot product of x and y: *
|
||||
* *
|
||||
* -> sum (i=0 to N-1) {x[i] * y[i]} *
|
||||
* *
|
||||
* Returns 0.0 if N <= 0. *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
real N_VDotProd(N_Vector x, N_Vector y);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VMaxNorm *
|
||||
* Usage : maxnorm = N_VMaxNorm(x); *
|
||||
*-------------------------------------------------------------*
|
||||
* *
|
||||
* Returns the maximum norm of x: *
|
||||
* *
|
||||
* -> max (i=0 to N-1) |x[i]| *
|
||||
* *
|
||||
* Returns 0.0 if N <= 0. *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
real N_VMaxNorm(N_Vector x);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VWrmsNorm *
|
||||
* Usage : wrmsnorm = N_VWrmsNorm(x, w); *
|
||||
*-------------------------------------------------------------*
|
||||
* *
|
||||
* Returns the weighted root mean square norm of x with *
|
||||
* weight vector w: *
|
||||
* *
|
||||
* -> sqrt [(sum (i=0 to N-1) {(x[i] * w[i])^2}) / N] *
|
||||
* *
|
||||
* Returns 0.0 if N <= 0. *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
real N_VWrmsNorm(N_Vector x, N_Vector w);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VMin *
|
||||
* Usage : min = N_VMin(x); *
|
||||
*-------------------------------------------------------------*
|
||||
* *
|
||||
* Returns min x[i] if N > 0 and returns 0.0 if N <= 0. *
|
||||
* i *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
real N_VMin(N_Vector x);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VWL2Norm *
|
||||
* Usage : wl2norm = N_VWL2Norm(x, w); *
|
||||
*-------------------------------------------------------------*
|
||||
* *
|
||||
* Returns the weighted Euclidean L2 norm of x with *
|
||||
* weight vector w: *
|
||||
* *
|
||||
* -> sqrt [(sum (i=0 to N-1) {(x[i] * w[i])^2}) ] *
|
||||
* *
|
||||
* Returns 0.0 if N <= 0. *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
real N_VWL2Norm(N_Vector x, N_Vector w);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VL1Norm *
|
||||
* Usage : l1norm = N_VL1Norm(x); *
|
||||
*-------------------------------------------------------------*
|
||||
* *
|
||||
* Returns sum of ABS(x[i]) if N > 0 and returns 0.0 if N <= 0.*
|
||||
* i *
|
||||
*
|
||||
* i.e., calculates and returns the L1 norm of x *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
real N_VL1Norm(N_Vector x);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Miscellaneous : N_VOneMask, N_VCompare, N_VInvTest, *
|
||||
* N_VConstrProdPos, N_VConstrMask, and N_VMinQuotient *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VOneMask *
|
||||
* Operation : x[i] = 1.0 if |x[i]| != 0. i = 0, 1, ..., N-1 *
|
||||
* 0.0 otherwise *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
void N_VOneMask(N_Vector x);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VCompare *
|
||||
* Operation : z[i] = 1.0 if |x[i]| >= c i = 0, 1, ..., N-1 *
|
||||
* 0.0 otherwise *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
|
||||
void N_VCompare(real c, N_Vector x, N_Vector z);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VInvTest *
|
||||
* Operation : z[i] = 1.0 / x[i] with a test for x[i]==0.0 *
|
||||
* before inverting x[i]. *
|
||||
*-------------------------------------------------------------*
|
||||
* *
|
||||
* This routine returns TRUE if all components of x are *
|
||||
* non-zero (successful inversion) and returns FALSE *
|
||||
* otherwise. *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
boole N_VInvTest(N_Vector x, N_Vector z);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VConstrProdPos *
|
||||
* Usage : booltest = N_VConstrProdPos(c,x); *
|
||||
*-------------------------------------------------------------*
|
||||
* *
|
||||
* Returns a boolean FALSE if some c[i]!=0.0 and x[i]*c[i]<=0.0*
|
||||
* and TRUE otherwise *
|
||||
* *
|
||||
* This routine is used for constraint checking. *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
boole N_VConstrProdPos(N_Vector c, N_Vector x);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VConstrMask *
|
||||
* Operation : m[i] = 1.0 , if constraint test fails, for i *
|
||||
* m[i] = 0.0 , if constraint test passes, for i *
|
||||
* where the constraint tests parallel those *
|
||||
* of routine N_VConstrProdPos *
|
||||
*-------------------------------------------------------------*
|
||||
* This routine returns a boole FALSE if any element failed *
|
||||
* the constraint test, TRUE if all passed. It also creates a *
|
||||
* mask vector, m, which has all elements whose corresponding *
|
||||
* constraint test failed, marked with 1.0, passed with 0.0 *
|
||||
* This routine is specialized in that it is used only for *
|
||||
* constraint checking. *
|
||||
***************************************************************/
|
||||
|
||||
boole N_VConstrMask(N_Vector c, N_Vector x, N_Vector m);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VMinQuotient *
|
||||
* Operation : minq = min ( num[i]/denom[i]) over all i such *
|
||||
* that denom[i] != 0. *
|
||||
*-------------------------------------------------------------*
|
||||
* *
|
||||
* This routine returns the minimum of the quotients obtained *
|
||||
* by term-wise dividing num[i] by denom[i]. A zero element *
|
||||
* in denom will be skipped. If no such quotients are found, *
|
||||
* then the large value 1.e99 is returned. *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
real N_VMinQuotient(N_Vector num, N_Vector denom);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Debugging Tools : N_VPrint *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
/***************************************************************
|
||||
* *
|
||||
* Function : N_VPrint *
|
||||
* Usage : N_VPrint(x); *
|
||||
*-------------------------------------------------------------*
|
||||
* *
|
||||
* Prints the N_Vector x to stdout. Each component of x is *
|
||||
* printed on a separate line using the %g specification. This *
|
||||
* routine is provided as an aid in debugging code which uses *
|
||||
* this vector package. *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
void N_VPrint(N_Vector x);
|
||||
|
||||
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,295 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* 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
|
||||
|
|
@ -1,356 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : band.c *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 25 February 2000 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the implementation file for a generic BAND linear *
|
||||
* solver package. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "band.h"
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
#include "llnlmath.h"
|
||||
|
||||
|
||||
#define ZERO RCONST(0.0)
|
||||
#define ONE RCONST(1.0)
|
||||
|
||||
#define ROW(i,j,smu) (i-j+smu)
|
||||
|
||||
|
||||
/* Implementation */
|
||||
|
||||
BandMat BandAllocMat(integer N, integer mu, integer ml, integer smu)
|
||||
{
|
||||
BandMat A;
|
||||
|
||||
if (N <= 0) return(NULL);
|
||||
|
||||
A = (BandMat) malloc(sizeof *A);
|
||||
if (A == NULL) return (NULL);
|
||||
|
||||
A->data = bandalloc(N, smu, ml);
|
||||
if (A->data == NULL) {
|
||||
free(A);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
A->size = N;
|
||||
A->mu = mu;
|
||||
A->ml = ml;
|
||||
A->smu = smu;
|
||||
|
||||
return(A);
|
||||
}
|
||||
|
||||
|
||||
integer *BandAllocPiv(integer N)
|
||||
{
|
||||
if (N <= 0) return(NULL);
|
||||
|
||||
return((integer *) malloc(N * sizeof(integer)));
|
||||
}
|
||||
|
||||
|
||||
integer BandFactor(BandMat A, integer *p)
|
||||
{
|
||||
return(gbfa(A->data, A->size, A->mu, A->ml, A->smu, p));
|
||||
}
|
||||
|
||||
|
||||
void BandBacksolve(BandMat A, integer *p, N_Vector b)
|
||||
{
|
||||
gbsl(A->data, A->size, A->smu, A->ml, p, N_VDATA(b));
|
||||
}
|
||||
|
||||
void BandZero(BandMat A)
|
||||
{
|
||||
bandzero(A->data, A->size, A->mu, A->ml, A->smu);
|
||||
}
|
||||
|
||||
void BandCopy(BandMat A, BandMat B, integer copymu, integer copyml)
|
||||
{
|
||||
bandcopy(A->data, B->data, A->size, A->smu, B->smu, copymu, copyml);
|
||||
}
|
||||
|
||||
void BandScale(real c, BandMat A)
|
||||
{
|
||||
bandscale(c, A->data, A->size, A->mu, A->ml, A->smu);
|
||||
}
|
||||
|
||||
void BandAddI(BandMat A)
|
||||
{
|
||||
bandaddI(A->data, A->size, A->smu);
|
||||
}
|
||||
|
||||
void BandFreeMat(BandMat A)
|
||||
{
|
||||
bandfree(A->data);
|
||||
free(A);
|
||||
}
|
||||
|
||||
void BandFreePiv(integer *p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
void BandPrint(BandMat A)
|
||||
{
|
||||
bandprint(A->data, A->size, A->mu, A->ml, A->smu);
|
||||
}
|
||||
|
||||
|
||||
real **bandalloc(integer n, integer smu, integer ml)
|
||||
{
|
||||
real **a;
|
||||
integer j, colSize;
|
||||
|
||||
if (n <= 0) return(NULL);
|
||||
|
||||
a = (real **) malloc(n * sizeof(real *));
|
||||
if (a == NULL) return(NULL);
|
||||
|
||||
colSize = smu + ml + 1;
|
||||
a[0] = (real *) malloc(n * colSize * sizeof(real));
|
||||
if (a[0] == NULL) {
|
||||
free(a);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
for (j=1; j < n; j++) a[j] = a[0] + j * colSize;
|
||||
|
||||
return(a);
|
||||
}
|
||||
|
||||
integer *bandallocpiv(integer n)
|
||||
{
|
||||
if (n <= 0) return(NULL);
|
||||
|
||||
return((integer *) malloc(n * sizeof(integer)));
|
||||
}
|
||||
|
||||
|
||||
integer gbfa(real **a, integer n, integer mu, integer ml, integer smu,
|
||||
integer *p)
|
||||
{
|
||||
integer c, r, num_rows;
|
||||
integer i, j, k, l, storage_l, storage_k, last_col_k, last_row_k;
|
||||
real *a_c, *col_k, *diag_k, *sub_diag_k, *col_j, *kptr, *jptr;
|
||||
real max, temp, mult, a_kj;
|
||||
boole swap;
|
||||
|
||||
/* zero out the first smu - mu rows of the rectangular array a */
|
||||
|
||||
num_rows = smu - mu;
|
||||
if (num_rows > 0) {
|
||||
for (c=0; c < n; c++) {
|
||||
a_c = a[c];
|
||||
for (r=0; r < num_rows; r++) {
|
||||
a_c[r] = ZERO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* k = elimination step number */
|
||||
|
||||
for (k=0; k < n-1; k++, p++) {
|
||||
|
||||
col_k = a[k];
|
||||
diag_k = col_k + smu;
|
||||
sub_diag_k = diag_k + 1;
|
||||
last_row_k = MIN(n-1,k+ml);
|
||||
|
||||
/* find l = pivot row number */
|
||||
|
||||
l=k;
|
||||
max = ABS(*diag_k);
|
||||
for (i=k+1, kptr=sub_diag_k; i <= last_row_k; i++, kptr++) {
|
||||
if (ABS(*kptr) > max) {
|
||||
l=i;
|
||||
max = ABS(*kptr);
|
||||
}
|
||||
}
|
||||
storage_l = ROW(l, k, smu);
|
||||
*p = l;
|
||||
|
||||
/* check for zero pivot element */
|
||||
|
||||
if (col_k[storage_l] == ZERO) return(k+1);
|
||||
|
||||
/* swap a(l,k) and a(k,k) if necessary */
|
||||
|
||||
if ( (swap = (l != k) )) {
|
||||
temp = col_k[storage_l];
|
||||
col_k[storage_l] = *diag_k;
|
||||
*diag_k = temp;
|
||||
}
|
||||
|
||||
/* Scale the elements below the diagonal in */
|
||||
/* column k by -1.0 / a(k,k). After the above swap, */
|
||||
/* a(k,k) holds the pivot element. This scaling */
|
||||
/* stores the pivot row multipliers -a(i,k)/a(k,k) */
|
||||
/* in a(i,k), i=k+1, ..., MIN(n-1,k+ml). */
|
||||
|
||||
mult = -ONE / (*diag_k);
|
||||
for (i=k+1, kptr = sub_diag_k; i <= last_row_k; i++, kptr++)
|
||||
(*kptr) *= mult;
|
||||
|
||||
/* row_i = row_i - [a(i,k)/a(k,k)] row_k, i=k+1, ..., MIN(n-1,k+ml) */
|
||||
/* row k is the pivot row after swapping with row l. */
|
||||
/* The computation is done one column at a time, */
|
||||
/* column j=k+1, ..., MIN(k+smu,n-1). */
|
||||
|
||||
last_col_k = MIN(k+smu,n-1);
|
||||
for (j=k+1; j <= last_col_k; j++) {
|
||||
|
||||
col_j = a[j];
|
||||
storage_l = ROW(l,j,smu);
|
||||
storage_k = ROW(k,j,smu);
|
||||
a_kj = col_j[storage_l];
|
||||
|
||||
/* Swap the elements a(k,j) and a(k,l) if l!=k. */
|
||||
|
||||
if (swap) {
|
||||
col_j[storage_l] = col_j[storage_k];
|
||||
col_j[storage_k] = a_kj;
|
||||
}
|
||||
|
||||
/* a(i,j) = a(i,j) - [a(i,k)/a(k,k)]*a(k,j) */
|
||||
/* a_kj = a(k,j), *kptr = - a(i,k)/a(k,k), *jptr = a(i,j) */
|
||||
|
||||
if (a_kj != ZERO) {
|
||||
for (i=k+1, kptr=sub_diag_k, jptr=col_j+ROW(k+1,j,smu);
|
||||
i <= last_row_k;
|
||||
i++, kptr++, jptr++)
|
||||
(*jptr) += a_kj * (*kptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set the last pivot row to be n-1 and check for a zero pivot */
|
||||
|
||||
*p = n-1;
|
||||
if (a[n-1][smu] == ZERO) return(n);
|
||||
|
||||
/* return 0 to indicate success */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void gbsl(real **a, integer n, integer smu, integer ml, integer *p,
|
||||
real *b)
|
||||
{
|
||||
integer k, l, i, first_row_k, last_row_k;
|
||||
real mult, *diag_k;
|
||||
|
||||
/* Solve Ly = Pb, store solution y in b */
|
||||
|
||||
for (k=0; k < n-1; k++) {
|
||||
l = p[k];
|
||||
mult = b[l];
|
||||
if (l != k) {
|
||||
b[l] = b[k];
|
||||
b[k] = mult;
|
||||
}
|
||||
diag_k = a[k]+smu;
|
||||
last_row_k = MIN(n-1,k+ml);
|
||||
for (i=k+1; i <= last_row_k; i++)
|
||||
b[i] += mult * diag_k[i-k];
|
||||
}
|
||||
|
||||
/* Solve Ux = y, store solution x in b */
|
||||
|
||||
for (k=n-1; k >= 0; k--) {
|
||||
diag_k = a[k]+smu;
|
||||
first_row_k = MAX(0,k-smu);
|
||||
b[k] /= (*diag_k);
|
||||
mult = -b[k];
|
||||
for (i=first_row_k; i <= k-1; i++)
|
||||
b[i] += mult*diag_k[i-k];
|
||||
}
|
||||
}
|
||||
|
||||
void bandzero(real **a, integer n, integer mu, integer ml, integer smu)
|
||||
{
|
||||
integer i, j, colSize;
|
||||
real *col_j;
|
||||
|
||||
colSize = mu + ml + 1;
|
||||
for (j=0; j < n; j++) {
|
||||
col_j = a[j]+smu-mu;
|
||||
for (i=0; i < colSize; i++)
|
||||
col_j[i] = ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
void bandcopy(real **a, real **b, integer n, integer a_smu, integer b_smu,
|
||||
integer copymu, integer copyml)
|
||||
{
|
||||
integer i, j, copySize;
|
||||
real *a_col_j, *b_col_j;
|
||||
|
||||
copySize = copymu + copyml + 1;
|
||||
|
||||
for (j=0; j < n; j++) {
|
||||
a_col_j = a[j]+a_smu-copymu;
|
||||
b_col_j = b[j]+b_smu-copymu;
|
||||
for (i=0; i < copySize; i++)
|
||||
b_col_j[i] = a_col_j[i];
|
||||
}
|
||||
}
|
||||
|
||||
void bandscale(real c, real **a, integer n, integer mu, integer ml,
|
||||
integer smu)
|
||||
{
|
||||
integer i, j, colSize;
|
||||
real *col_j;
|
||||
|
||||
colSize = mu + ml + 1;
|
||||
|
||||
for(j=0; j < n; j++) {
|
||||
col_j = a[j]+smu-mu;
|
||||
for (i=0; i < colSize; i++)
|
||||
col_j[i] *= c;
|
||||
}
|
||||
}
|
||||
|
||||
void bandaddI(real **a, integer n, integer smu)
|
||||
{
|
||||
integer j;
|
||||
|
||||
for(j=0; j < n; j++)
|
||||
a[j][smu] += ONE;
|
||||
}
|
||||
|
||||
void bandfreepiv(integer *p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
void bandfree(real **a)
|
||||
{
|
||||
free(a[0]);
|
||||
free(a);
|
||||
}
|
||||
|
||||
void bandprint(real **a, integer n, integer mu, integer ml, integer smu)
|
||||
{
|
||||
integer i, j, start, finish;
|
||||
|
||||
printf("\n");
|
||||
for (i=0; i < n; i++) {
|
||||
start = MAX(0,i-ml);
|
||||
finish = MIN(n-1,i+mu);
|
||||
for (j=0; j < start; j++) printf("%10s","");
|
||||
for (j=start; j <= finish; j++) {
|
||||
printf("%10g", a[j][i-j+smu]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
|
@ -1,415 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : cvband.c *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 24 February 2000 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the implementation file for the CVODE band linear *
|
||||
* solver, CVBAND. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "cvband.h"
|
||||
#include "cvode.h"
|
||||
#include "band.h"
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
#include "llnlmath.h"
|
||||
|
||||
|
||||
/* Error Messages */
|
||||
|
||||
#define CVBAND_INIT "CVBandInit-- "
|
||||
|
||||
#define MSG_MEM_FAIL CVBAND_INIT "A memory request failed.\n\n"
|
||||
|
||||
#define MSG_BAD_SIZES_1 CVBAND_INIT "Illegal bandwidth parameter(s) "
|
||||
#define MSG_BAD_SIZES_2 "ml = %ld, mu = %ld.\n"
|
||||
#define MSG_BAD_SIZES_3 "Must have 0 <= ml, mu <= N-1=%ld.\n\n"
|
||||
#define MSG_BAD_SIZES MSG_BAD_SIZES_1 MSG_BAD_SIZES_2 MSG_BAD_SIZES_3
|
||||
|
||||
|
||||
/* Other Constants */
|
||||
|
||||
#define MIN_INC_MULT RCONST(1000.0)
|
||||
#define ZERO RCONST(0.0)
|
||||
#define ONE RCONST(1.0)
|
||||
#define TWO RCONST(2.0)
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Types : CVBandMemRec, CVBandMem *
|
||||
*----------------------------------------------------------------*
|
||||
* The type CVBandMem is pointer to a CVBandMemRec. This *
|
||||
* structure contains CVBand solver-specific data. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
typedef struct {
|
||||
|
||||
CVBandJacFn b_jac; /* jac = Jacobian routine to be called */
|
||||
|
||||
integer b_ml; /* b_ml = lower bandwidth of savedJ */
|
||||
|
||||
integer b_mu; /* b_mu = upper bandwidth of savedJ */
|
||||
|
||||
integer b_storage_mu; /* upper bandwith of M = MIN(N-1,b_mu+b_ml) */
|
||||
|
||||
BandMat b_M; /* M = I - gamma J, gamma = h / l1 */
|
||||
|
||||
integer *b_pivots; /* pivots = pivot array for PM = LU */
|
||||
|
||||
BandMat b_savedJ; /* savedJ = old Jacobian */
|
||||
|
||||
long int b_nstlj; /* nstlj = nst at last Jacobian eval. */
|
||||
|
||||
long int b_nje; /* nje = no. of calls to jac */
|
||||
|
||||
void *b_J_data; /* J_data is passed to jac */
|
||||
|
||||
} CVBandMemRec, *CVBandMem;
|
||||
|
||||
|
||||
/* CVBAND linit, lsetup, lsolve, and lfree routines */
|
||||
|
||||
static int CVBandInit(CVodeMem cv_mem, boole *setupNonNull);
|
||||
|
||||
static int CVBandSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
|
||||
N_Vector fpred, boole *jcurPtr, N_Vector vtemp1,
|
||||
N_Vector vtemp2, N_Vector vtemp3);
|
||||
|
||||
static int CVBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector ycur,
|
||||
N_Vector fcur);
|
||||
|
||||
static void CVBandFree(CVodeMem cv_mem);
|
||||
|
||||
|
||||
/*************** CVBandDQJac *****************************************
|
||||
|
||||
This routine generates a banded difference quotient approximation to
|
||||
the Jacobian of f(t,y). It assumes that a band matrix of type
|
||||
BandMat is stored column-wise, and that elements within each column
|
||||
are contiguous. This makes it possible to get the address of a column
|
||||
of J via the macro BAND_COL and to write a simple for loop to set
|
||||
each of the elements of a column in succession.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
void CVBandDQJac(integer N, integer mupper, integer mlower, BandMat J,
|
||||
RhsFn f, void *f_data, real tn, N_Vector y,
|
||||
N_Vector fy, N_Vector ewt, real h, real uround,
|
||||
void *jac_data, long int *nfePtr, N_Vector vtemp1,
|
||||
N_Vector vtemp2, N_Vector vtemp3)
|
||||
{
|
||||
real fnorm, minInc, inc, inc_inv, srur;
|
||||
N_Vector ftemp, ytemp;
|
||||
integer group, i, j, width, ngroups, i1, i2;
|
||||
real *col_j, *ewt_data, *fy_data, *ftemp_data, *y_data, *ytemp_data;
|
||||
|
||||
/* Rename work vectors for use as temporary values of y and f */
|
||||
ftemp = vtemp1;
|
||||
ytemp = vtemp2;
|
||||
|
||||
/* Obtain pointers to the data for ewt, fy, ftemp, y, ytemp */
|
||||
ewt_data = N_VDATA(ewt);
|
||||
fy_data = N_VDATA(fy);
|
||||
ftemp_data = N_VDATA(ftemp);
|
||||
y_data = N_VDATA(y);
|
||||
ytemp_data = N_VDATA(ytemp);
|
||||
|
||||
/* Load ytemp with y = predicted y vector */
|
||||
N_VScale(ONE, y, ytemp);
|
||||
|
||||
/* Set minimum increment based on uround and norm of f */
|
||||
srur = RSqrt(uround);
|
||||
fnorm = N_VWrmsNorm(fy, ewt);
|
||||
minInc = (fnorm != ZERO) ?
|
||||
(MIN_INC_MULT * ABS(h) * uround * N * fnorm) : ONE;
|
||||
|
||||
/* Set bandwidth and number of column groups for band differencing */
|
||||
width = mlower + mupper + 1;
|
||||
ngroups = MIN(width, N);
|
||||
|
||||
for (group=1; group <= ngroups; group++) {
|
||||
|
||||
/* Increment all y_j in group */
|
||||
for(j=group-1; j < N; j+=width) {
|
||||
inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]);
|
||||
ytemp_data[j] += inc;
|
||||
}
|
||||
|
||||
/* Evaluate f with incremented y */
|
||||
f(N, tn, ytemp, ftemp, f_data);
|
||||
|
||||
/* Restore ytemp, then form and load difference quotients */
|
||||
for (j=group-1; j < N; j+=width) {
|
||||
ytemp_data[j] = y_data[j];
|
||||
col_j = BAND_COL(J,j);
|
||||
inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]);
|
||||
inc_inv = ONE/inc;
|
||||
i1 = MAX(0, j-mupper);
|
||||
i2 = MIN(j+mlower, N-1);
|
||||
for (i=i1; i <= i2; i++)
|
||||
BAND_COL_ELEM(col_j,i,j) =
|
||||
inc_inv * (ftemp_data[i] - fy_data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment counter nfe = *nfePtr */
|
||||
*nfePtr += ngroups;
|
||||
}
|
||||
|
||||
|
||||
/* Readability Replacements */
|
||||
|
||||
#define N (cv_mem->cv_N)
|
||||
#define lmm (cv_mem->cv_lmm)
|
||||
#define f (cv_mem->cv_f)
|
||||
#define f_data (cv_mem->cv_f_data)
|
||||
#define uround (cv_mem->cv_uround)
|
||||
#define nst (cv_mem->cv_nst)
|
||||
#define tn (cv_mem->cv_tn)
|
||||
#define h (cv_mem->cv_h)
|
||||
#define gamma (cv_mem->cv_gamma)
|
||||
#define gammap (cv_mem->cv_gammap)
|
||||
#define gamrat (cv_mem->cv_gamrat)
|
||||
#define ewt (cv_mem->cv_ewt)
|
||||
#define nfe (cv_mem->cv_nfe)
|
||||
#define errfp (cv_mem->cv_errfp)
|
||||
#define iopt (cv_mem->cv_iopt)
|
||||
#define linit (cv_mem->cv_linit)
|
||||
#define lsetup (cv_mem->cv_lsetup)
|
||||
#define lsolve (cv_mem->cv_lsolve)
|
||||
#define lfree (cv_mem->cv_lfree)
|
||||
#define lmem (cv_mem->cv_lmem)
|
||||
|
||||
#define jac (cvband_mem->b_jac)
|
||||
#define M (cvband_mem->b_M)
|
||||
#define mu (cvband_mem->b_mu)
|
||||
#define ml (cvband_mem->b_ml)
|
||||
#define storage_mu (cvband_mem->b_storage_mu)
|
||||
#define pivots (cvband_mem->b_pivots)
|
||||
#define savedJ (cvband_mem->b_savedJ)
|
||||
#define nstlj (cvband_mem->b_nstlj)
|
||||
#define nje (cvband_mem->b_nje)
|
||||
#define J_data (cvband_mem->b_J_data)
|
||||
|
||||
|
||||
/*************** CVBand **********************************************
|
||||
|
||||
This routine initializes the memory record and sets various function
|
||||
fields specific to the band linear solver module. CVBand sets the
|
||||
cv_linit, cv_lsetup, cv_lsolve, and cv_lfree fields in (*cvode_mem)
|
||||
to be CVBandInit, CVBandSetup, CVBandSolve, and CVBandFree,
|
||||
respectively. It allocates memory for a structure of type
|
||||
CVBandMemRec and sets the cv_lmem field in (*cvode_mem) to the
|
||||
address of this structure. Finally, it sets b_J_data field in the
|
||||
CVBandMemRec structure to be the input parameter jac_data, b_mu to
|
||||
be mupper, b_ml to be mlower, and the b_jac field to be:
|
||||
|
||||
(1) the input parameter bjac if bjac != NULL or
|
||||
|
||||
(2) CVBandDQJac if bjac == NULL.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
void CVBand(void *cvode_mem, integer mupper, integer mlower, CVBandJacFn bjac,
|
||||
void *jac_data)
|
||||
{
|
||||
CVodeMem cv_mem;
|
||||
CVBandMem cvband_mem;
|
||||
|
||||
/* Return immediately if cvode_mem is NULL */
|
||||
cv_mem = (CVodeMem) cvode_mem;
|
||||
if (cv_mem == NULL) return; /* CVode reports this error */
|
||||
|
||||
/* Set four main function fields in cv_mem */
|
||||
linit = CVBandInit;
|
||||
lsetup = CVBandSetup;
|
||||
lsolve = CVBandSolve;
|
||||
lfree = CVBandFree;
|
||||
|
||||
/* Get memory for CVBandMemRec */
|
||||
lmem = cvband_mem = (CVBandMem) malloc(sizeof(CVBandMemRec));
|
||||
if (cvband_mem == NULL) return; /* CVBandInit reports this error */
|
||||
|
||||
/* Set Jacobian routine field to user's bjac or CVBandDQJac */
|
||||
if (bjac == NULL) {
|
||||
jac = CVBandDQJac;
|
||||
} else {
|
||||
jac = bjac;
|
||||
}
|
||||
J_data = jac_data;
|
||||
|
||||
/* Load half-bandwiths in cvband_mem */
|
||||
ml = mlower;
|
||||
mu = mupper;
|
||||
}
|
||||
|
||||
/*************** CVBandInit ******************************************
|
||||
|
||||
This routine initializes remaining memory specific to the band
|
||||
linear solver. If any memory request fails, all memory previously
|
||||
allocated is freed, and an error message printed, before returning.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static int CVBandInit(CVodeMem cv_mem, boole *setupNonNull)
|
||||
{
|
||||
CVBandMem cvband_mem;
|
||||
|
||||
cvband_mem = (CVBandMem) lmem;
|
||||
|
||||
/* Print error message and return if cvband_mem is NULL */
|
||||
if (cvband_mem == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
|
||||
/* Set flag setupNonNull = TRUE */
|
||||
*setupNonNull = TRUE;
|
||||
|
||||
/* Test ml and mu for legality */
|
||||
if ((ml < 0) || (mu < 0) || (ml >= N) || (mu >= N)) {
|
||||
fprintf(errfp, MSG_BAD_SIZES, ml, mu, N-1);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
|
||||
/* Set extended upper half-bandwith for M (required for pivoting) */
|
||||
storage_mu = MIN(N-1, mu + ml);
|
||||
|
||||
/* Allocate memory for M, savedJ, and pivot arrays */
|
||||
M = BandAllocMat(N, mu, ml, storage_mu);
|
||||
if (M == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
savedJ = BandAllocMat(N, mu, ml, mu);
|
||||
if (savedJ == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
BandFreeMat(M);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
pivots = BandAllocPiv(N);
|
||||
if (pivots == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
BandFreeMat(M);
|
||||
BandFreeMat(savedJ);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
|
||||
/* Initialize nje and nstlj, and set workspace lengths */
|
||||
nje = 0;
|
||||
if (iopt != NULL) {
|
||||
iopt[BAND_NJE] = nje;
|
||||
iopt[BAND_LRW] = N*(storage_mu + mu + 2*ml + 2);
|
||||
iopt[BAND_LIW] = N;
|
||||
}
|
||||
nstlj = 0;
|
||||
|
||||
return(LINIT_OK);
|
||||
}
|
||||
|
||||
/*************** CVBandSetup *****************************************
|
||||
|
||||
This routine does the setup operations for the band linear solver.
|
||||
It makes a decision whether or not to call the Jacobian evaluation
|
||||
routine based on various state variables, and if not it uses the
|
||||
saved copy. In any case, it constructs the Newton matrix
|
||||
M = I - gamma*J, updates counters, and calls the band LU
|
||||
factorization routine.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static int CVBandSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
|
||||
N_Vector fpred, boole *jcurPtr, N_Vector vtemp1,
|
||||
N_Vector vtemp2, N_Vector vtemp3)
|
||||
{
|
||||
boole jbad, jok;
|
||||
real dgamma;
|
||||
integer ier;
|
||||
CVBandMem cvband_mem;
|
||||
|
||||
cvband_mem = (CVBandMem) lmem;
|
||||
|
||||
/* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
|
||||
|
||||
dgamma = ABS((gamma/gammap) - ONE);
|
||||
jbad = (nst == 0) || (nst > nstlj + CVB_MSBJ) ||
|
||||
((convfail == FAIL_BAD_J) && (dgamma < CVB_DGMAX)) ||
|
||||
(convfail == FAIL_OTHER);
|
||||
jok = !jbad;
|
||||
|
||||
if (jok) {
|
||||
/* If jok = TRUE, use saved copy of J */
|
||||
*jcurPtr = FALSE;
|
||||
BandCopy(savedJ, M, mu, ml);
|
||||
} else {
|
||||
/* If jok = FALSE, call jac routine for new J value */
|
||||
nje++;
|
||||
if (iopt != NULL) iopt[BAND_NJE] = nje;
|
||||
nstlj = nst;
|
||||
*jcurPtr = TRUE;
|
||||
BandZero(M);
|
||||
jac(N, mu, ml, M, f, f_data, tn, ypred, fpred, ewt,
|
||||
h, uround, J_data, &nfe, vtemp1, vtemp2, vtemp3);
|
||||
BandCopy(M, savedJ, mu, ml);
|
||||
}
|
||||
|
||||
/* Scale and add I to get M = I - gamma*J */
|
||||
BandScale(-gamma, M);
|
||||
BandAddI(M);
|
||||
|
||||
/* Do LU factorization of M */
|
||||
ier = BandFactor(M, pivots);
|
||||
|
||||
/* Return 0 if the LU was complete; otherwise return 1 */
|
||||
if (ier > 0) return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*************** CVBandSolve *****************************************
|
||||
|
||||
This routine handles the solve operation for the band linear solver
|
||||
by calling the band backsolve routine. The return value is 0.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static int CVBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector ycur,
|
||||
N_Vector fcur)
|
||||
{
|
||||
CVBandMem cvband_mem;
|
||||
|
||||
cvband_mem = (CVBandMem) lmem;
|
||||
|
||||
BandBacksolve(M, pivots, b);
|
||||
|
||||
/* If BDF, scale the correction to account for change in gamma */
|
||||
if ((lmm == BDF) && (gamrat != ONE)) {
|
||||
N_VScale(TWO/(ONE + gamrat), b, b);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*************** CVBandFree ******************************************
|
||||
|
||||
This routine frees memory specific to the band linear solver.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static void CVBandFree(CVodeMem cv_mem)
|
||||
{
|
||||
CVBandMem cvband_mem;
|
||||
|
||||
cvband_mem = (CVBandMem) lmem;
|
||||
|
||||
BandFreeMat(M);
|
||||
BandFreeMat(savedJ);
|
||||
BandFreePiv(pivots);
|
||||
free(lmem);
|
||||
}
|
||||
|
|
@ -1,318 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : cvbandpre.c *
|
||||
* Programmers : Michael Wittman and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 23 March 2000 *
|
||||
*----------------------------------------------------------------*
|
||||
* This file contains implementations of the banded difference *
|
||||
* quotient Jacobian-based preconditioner and solver routines for *
|
||||
* use with CVSpgmr. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "cvbandpre.h"
|
||||
#include "cvode.h"
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
#include "llnlmath.h"
|
||||
#include "band.h"
|
||||
|
||||
#define MIN_INC_MULT RCONST(1000.0)
|
||||
#define ZERO RCONST(0.0)
|
||||
#define ONE RCONST(1.0)
|
||||
|
||||
/* Prototype for difference quotient Jacobian calculation routine */
|
||||
|
||||
static void CVBandPDQJac(integer N, integer mupper, integer mlower, BandMat J,
|
||||
RhsFn f, void *f_data, real tn, N_Vector y,
|
||||
N_Vector fy, N_Vector ewt, real h, real uround,
|
||||
N_Vector ftemp, N_Vector ytemp);
|
||||
|
||||
|
||||
/********************** Malloc and Free Functions **********************/
|
||||
|
||||
CVBandPreData CVBandPreAlloc(integer N, RhsFn f, void *f_data,
|
||||
integer mu, integer ml)
|
||||
{
|
||||
CVBandPreData pdata;
|
||||
integer mup, mlp, storagemu;
|
||||
|
||||
pdata = (CVBandPreData) malloc(sizeof *pdata); /* Allocate data memory */
|
||||
if (pdata == NULL) return(NULL);
|
||||
|
||||
/* Load pointers and bandwidths into pdata block. */
|
||||
pdata->f = f;
|
||||
pdata->f_data = f_data;
|
||||
pdata->mu = mup = MIN( N-1, MAX(0,mu) );
|
||||
pdata->ml = mlp = MIN( N-1, MAX(0,ml) );
|
||||
|
||||
/* Allocate memory for saved banded Jacobian approximation. */
|
||||
pdata->savedJ = BandAllocMat(N, mup, mlp, mup);
|
||||
if (pdata->savedJ == NULL) {
|
||||
free(pdata);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Allocate memory for banded preconditioner. */
|
||||
storagemu = MIN( N-1, mup + mlp);
|
||||
pdata->savedP = BandAllocMat(N, mup, mlp, storagemu);
|
||||
if (pdata->savedP == NULL) {
|
||||
BandFreeMat(pdata->savedJ);
|
||||
free(pdata);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Allocate memory for pivot array. */
|
||||
pdata->pivots = BandAllocPiv(N);
|
||||
if (pdata->savedJ == NULL) {
|
||||
BandFreeMat(pdata->savedP);
|
||||
BandFreeMat(pdata->savedJ);
|
||||
free(pdata);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(pdata);
|
||||
}
|
||||
|
||||
void CVBandPreFree(CVBandPreData pdata)
|
||||
{
|
||||
BandFreeMat(pdata->savedJ);
|
||||
BandFreeMat(pdata->savedP);
|
||||
BandFreePiv(pdata->pivots);
|
||||
free(pdata);
|
||||
}
|
||||
|
||||
|
||||
/***************** Preconditioner setup and solve functions *******/
|
||||
|
||||
|
||||
/* Readability Replacements */
|
||||
|
||||
#define f (pdata->f)
|
||||
#define f_data (pdata->f_data)
|
||||
#define mu (pdata->mu)
|
||||
#define ml (pdata->ml)
|
||||
#define pivots (pdata->pivots)
|
||||
#define savedJ (pdata->savedJ)
|
||||
#define savedP (pdata->savedP)
|
||||
|
||||
|
||||
/* Preconditioner setup routine CVBandPrecond. */
|
||||
|
||||
/******************************************************************
|
||||
* Together CVBandPrecond and CVBandPSolve use a banded *
|
||||
* difference quotient Jacobian to create a preconditioner. *
|
||||
* CVBandPrecond calculates a new J, if necessary, then *
|
||||
* calculates P = I - gamma*J, and does an LU factorization of P. *
|
||||
* *
|
||||
* The parameters of CVBandPrecond are as follows: *
|
||||
* *
|
||||
* N is the length of all vector arguments. *
|
||||
* *
|
||||
* t is the current value of the independent variable. *
|
||||
* *
|
||||
* y is the current value of the dependent variable vector, *
|
||||
* namely the predicted value of y(t). *
|
||||
* *
|
||||
* fy is the vector f(t,y). *
|
||||
* *
|
||||
* jok is an input flag indicating whether Jacobian-related *
|
||||
* data needs to be recomputed, as follows: *
|
||||
* jok == FALSE means recompute Jacobian-related data *
|
||||
* from scratch. *
|
||||
* jok == TRUE means that Jacobian data from the *
|
||||
* previous Precond call will be reused *
|
||||
* (with the current value of gamma). *
|
||||
* A CVBandPrecond call with jok == TRUE should only *
|
||||
* occur after a call with jok == FALSE. *
|
||||
* *
|
||||
* jcurPtr is a pointer to an output integer flag which is *
|
||||
* set by CVBandPrecond as follows: *
|
||||
* *jcurPtr = TRUE if Jacobian data was recomputed. *
|
||||
* *jcurPtr = FALSE if Jacobian data was not recomputed,*
|
||||
* but saved data was reused. *
|
||||
* *
|
||||
* gamma is the scalar appearing in the Newton matrix. *
|
||||
* *
|
||||
* ewt is the error weight vector. *
|
||||
* *
|
||||
* h is a tentative step size in t. *
|
||||
* *
|
||||
* uround is the machine unit roundoff. *
|
||||
* *
|
||||
* nfePtr is a pointer to the memory location containing the *
|
||||
* CVODE problem data nfe = number of calls to f. *
|
||||
* The routine calls f a total of ml+mu+1 times, so *
|
||||
* it increments *nfePtr by ml+mu+1. *
|
||||
* *
|
||||
* bp_data is a pointer to preconditoner data - the same as the *
|
||||
* bp_data parameter passed to CVSpgmr. *
|
||||
* *
|
||||
* vtemp1, vtemp2, and vtemp3 are pointers to memory allocated *
|
||||
* for vectors of length N for work space. This *
|
||||
* routine uses only vtemp1 and vtemp2. *
|
||||
* *
|
||||
* *
|
||||
* The value to be returned by the CVBandPrecond function is *
|
||||
* 0 if successful, or *
|
||||
* 1 if the band factorization failed. *
|
||||
******************************************************************/
|
||||
|
||||
int CVBandPrecond(integer N, real t, N_Vector y, N_Vector fy,
|
||||
boole jok, boole *jcurPtr, real gamma,
|
||||
N_Vector ewt, real h, real uround,
|
||||
long int *nfePtr, void *bp_data,
|
||||
N_Vector vtemp1, N_Vector vtemp2,
|
||||
N_Vector vtemp3)
|
||||
{
|
||||
integer ier;
|
||||
CVBandPreData pdata;
|
||||
|
||||
/* Assume matrix and pivots have already been allocated. */
|
||||
pdata = (CVBandPreData) bp_data;
|
||||
|
||||
if (jok) {
|
||||
/* If jok = TRUE, use saved copy of J. */
|
||||
*jcurPtr = FALSE;
|
||||
BandCopy(savedJ, savedP, mu, ml);
|
||||
} else {
|
||||
/* If jok = FALSE, call CVBandPDQJac for new J value. */
|
||||
*jcurPtr = TRUE;
|
||||
BandZero(savedJ);
|
||||
CVBandPDQJac(N, mu, ml, savedJ, f, f_data, t, y, fy, ewt,
|
||||
h, uround, vtemp1, vtemp2);
|
||||
BandCopy(savedJ, savedP, mu, ml);
|
||||
*nfePtr += MIN( N, ml + mu + 1 );
|
||||
}
|
||||
|
||||
/* Scale and add I to get savedP = I - gamma*J. */
|
||||
BandScale(-gamma, savedP);
|
||||
BandAddI(savedP);
|
||||
|
||||
/* Do LU factorization of matrix. */
|
||||
ier = BandFactor(savedP, pivots);
|
||||
|
||||
/* Return 0 if the LU was complete; otherwise return 1. */
|
||||
if (ier > 0) return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Preconditioner solve routine CVBandPSolve */
|
||||
|
||||
/******************************************************************
|
||||
* CVBandPSolve solves a linear system P z = r, where P is the *
|
||||
* matrix computed by CVBandPrecond. *
|
||||
* *
|
||||
* The parameters of CVBandPSolve used here are as follows: *
|
||||
* *
|
||||
* r is the right-hand side vector of the linear system. *
|
||||
* *
|
||||
* bp_data is a pointer to preconditioner data - the same as the *
|
||||
* bp_data parameter passed to CVSpgmr. *
|
||||
* *
|
||||
* z is the output vector computed by CVBandPSolve. *
|
||||
* *
|
||||
* The value returned by the CVBandPSolve function is always 0, *
|
||||
* indicating success. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
int CVBandPSolve(integer N, real t, N_Vector y, N_Vector fy,
|
||||
N_Vector vtemp, real gamma, N_Vector ewt,
|
||||
real delta, long int *nfePtr, N_Vector r,
|
||||
int lr, void *bp_data, N_Vector z)
|
||||
{
|
||||
CVBandPreData pdata;
|
||||
|
||||
/* Assume matrix and pivots have already been allocated. */
|
||||
pdata = (CVBandPreData) bp_data;
|
||||
|
||||
/* Copy r to z. */
|
||||
N_VScale(ONE, r, z);
|
||||
|
||||
/* Do band backsolve on the vector z. */
|
||||
BandBacksolve(savedP, pivots, z);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
#undef f
|
||||
#undef f_data
|
||||
#undef mu
|
||||
#undef ml
|
||||
#undef pivots
|
||||
#undef savedJ
|
||||
#undef savedP
|
||||
|
||||
|
||||
|
||||
|
||||
/*************** CVBandPDQJac ****************************************
|
||||
|
||||
This routine generates a banded difference quotient approximation to
|
||||
the Jacobian of f(t,y). It assumes that a band matrix of type
|
||||
BandMat is stored column-wise, and that elements within each column
|
||||
are contiguous. This makes it possible to get the address of a column
|
||||
of J via the macro BAND_COL and to write a simple for loop to set
|
||||
each of the elements of a column in succession.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static void CVBandPDQJac(integer N, integer mupper, integer mlower, BandMat J,
|
||||
RhsFn f, void *f_data, real tn, N_Vector y,
|
||||
N_Vector fy, N_Vector ewt, real h, real uround,
|
||||
N_Vector ftemp, N_Vector ytemp)
|
||||
{
|
||||
real fnorm, minInc, inc, inc_inv, srur;
|
||||
integer group, i, j, width, ngroups, i1, i2;
|
||||
real *col_j, *ewt_data, *fy_data, *ftemp_data, *y_data, *ytemp_data;
|
||||
|
||||
/* Obtain pointers to the data for ewt, fy, ftemp, y, ytemp. */
|
||||
ewt_data = N_VDATA(ewt);
|
||||
fy_data = N_VDATA(fy);
|
||||
ftemp_data = N_VDATA(ftemp);
|
||||
y_data = N_VDATA(y);
|
||||
ytemp_data = N_VDATA(ytemp);
|
||||
|
||||
/* Load ytemp with y = predicted y vector. */
|
||||
N_VScale(ONE, y, ytemp);
|
||||
|
||||
/* Set minimum increment based on uround and norm of f. */
|
||||
srur = RSqrt(uround);
|
||||
fnorm = N_VWrmsNorm(fy, ewt);
|
||||
minInc = (fnorm != ZERO) ?
|
||||
(MIN_INC_MULT * ABS(h) * uround * N * fnorm) : ONE;
|
||||
|
||||
/* Set bandwidth and number of column groups for band differencing. */
|
||||
width = mlower + mupper + 1;
|
||||
ngroups = MIN(width, N);
|
||||
|
||||
for (group = 1; group <= ngroups; group++) {
|
||||
|
||||
/* Increment all y_j in group. */
|
||||
for(j = group-1; j < N; j += width) {
|
||||
inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]);
|
||||
ytemp_data[j] += inc;
|
||||
}
|
||||
|
||||
/* Evaluate f with incremented y. */
|
||||
f(N, tn, ytemp, ftemp, f_data);
|
||||
|
||||
/* Restore ytemp, then form and load difference quotients. */
|
||||
for (j = group-1; j < N; j += width) {
|
||||
ytemp_data[j] = y_data[j];
|
||||
col_j = BAND_COL(J,j);
|
||||
inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]);
|
||||
inc_inv = ONE/inc;
|
||||
i1 = MAX(0, j-mupper);
|
||||
i2 = MIN(j+mlower, N-1);
|
||||
for (i=i1; i <= i2; i++)
|
||||
BAND_COL_ELEM(col_j,i,j) =
|
||||
inc_inv * (ftemp_data[i] - fy_data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,372 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : cvdense.c *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 25 February 2000 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the implementation file for the CVODE dense linear *
|
||||
* solver, CVDENSE. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "cvdense.h"
|
||||
#include "cvode.h"
|
||||
#include "dense.h"
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
#include "llnlmath.h"
|
||||
|
||||
|
||||
/* Error Messages */
|
||||
|
||||
#define CVDENSE_INIT "CVDenseInit-- "
|
||||
|
||||
#define MSG_MEM_FAIL CVDENSE_INIT "A memory request failed.\n\n"
|
||||
|
||||
|
||||
/* Other Constants */
|
||||
|
||||
#define MIN_INC_MULT RCONST(1000.0)
|
||||
#define ZERO RCONST(0.0)
|
||||
#define ONE RCONST(1.0)
|
||||
#define TWO RCONST(2.0)
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Types : CVDenseMemRec, CVDenseMem *
|
||||
*----------------------------------------------------------------*
|
||||
* The type CVDenseMem is pointer to a CVDenseMemRec. This *
|
||||
* structure contains CVDense solver-specific data. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
typedef struct {
|
||||
|
||||
CVDenseJacFn d_jac; /* jac = Jacobian routine to be called */
|
||||
|
||||
DenseMat d_M; /* M = I - gamma J, gamma = h / l1 */
|
||||
|
||||
integer *d_pivots; /* pivots = pivot array for PM = LU */
|
||||
|
||||
DenseMat d_savedJ; /* savedJ = old Jacobian */
|
||||
|
||||
long int d_nstlj; /* nstlj = nst at last Jacobian eval. */
|
||||
|
||||
long int d_nje; /* nje = no. of calls to jac */
|
||||
|
||||
void *d_J_data; /* J_data is passed to jac */
|
||||
|
||||
} CVDenseMemRec, *CVDenseMem;
|
||||
|
||||
|
||||
/* CVDENSE linit, lsetup, lsolve, and lfree routines */
|
||||
|
||||
static int CVDenseInit(CVodeMem cv_mem, boole *setupNonNull);
|
||||
|
||||
static int CVDenseSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
|
||||
N_Vector fpred, boole *jcurPtr, N_Vector vtemp1,
|
||||
N_Vector vtemp2, N_Vector vtemp3);
|
||||
|
||||
static int CVDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector ycur,
|
||||
N_Vector fcur);
|
||||
|
||||
static void CVDenseFree(CVodeMem cv_mem);
|
||||
|
||||
|
||||
/*************** CVDenseDQJac ****************************************
|
||||
|
||||
This routine generates a dense difference quotient approximation to
|
||||
the Jacobian of f(t,y). It assumes that a dense matrix of type
|
||||
DenseMat is stored column-wise, and that elements within each column
|
||||
are contiguous. The address of the jth column of J is obtained via
|
||||
the macro DENSE_COL and an N_Vector with the jth column as the
|
||||
component array is created using N_VMAKE and N_VDATA. Finally, the
|
||||
actual computation of the jth column of the Jacobian is done with a
|
||||
call to N_VLinearSum.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
void CVDenseDQJac(integer N, DenseMat J, RhsFn f, void *f_data, real tn,
|
||||
N_Vector y, N_Vector fy, N_Vector ewt, real h, real uround,
|
||||
void *jac_data, long int *nfePtr, N_Vector vtemp1,
|
||||
N_Vector vtemp2, N_Vector vtemp3)
|
||||
{
|
||||
real fnorm, minInc, inc, inc_inv, yjsaved, srur;
|
||||
real *y_data, *ewt_data;
|
||||
N_Vector ftemp, jthCol;
|
||||
integer j;
|
||||
|
||||
ftemp = vtemp1; /* Rename work vector for use as f vector value */
|
||||
|
||||
/* Obtain pointers to the data for ewt, y */
|
||||
ewt_data = N_VDATA(ewt);
|
||||
y_data = N_VDATA(y);
|
||||
|
||||
/* Set minimum increment based on uround and norm of f */
|
||||
srur = RSqrt(uround);
|
||||
fnorm = N_VWrmsNorm(fy, ewt);
|
||||
minInc = (fnorm != ZERO) ?
|
||||
(MIN_INC_MULT * ABS(h) * uround * N * fnorm) : ONE;
|
||||
|
||||
N_VMAKE(jthCol, y_data, N); /* j loop overwrites this data address */
|
||||
|
||||
/* This is the only for loop for 0..N-1 in CVODE */
|
||||
for (j = 0; j < N; j++) {
|
||||
|
||||
/* Generate the jth col of J(tn,y) */
|
||||
|
||||
N_VDATA(jthCol) = DENSE_COL(J,j);
|
||||
yjsaved = y_data[j];
|
||||
inc = MAX(srur*ABS(yjsaved), minInc/ewt_data[j]);
|
||||
y_data[j] += inc;
|
||||
f(N, tn, y, ftemp, f_data);
|
||||
inc_inv = ONE/inc;
|
||||
N_VLinearSum(inc_inv, ftemp, -inc_inv, fy, jthCol);
|
||||
y_data[j] = yjsaved;
|
||||
}
|
||||
|
||||
N_VDISPOSE(jthCol);
|
||||
|
||||
/* Increment counter nfe = *nfePtr */
|
||||
*nfePtr += N;
|
||||
}
|
||||
|
||||
|
||||
/* Readability Replacements */
|
||||
|
||||
#define N (cv_mem->cv_N)
|
||||
#define lmm (cv_mem->cv_lmm)
|
||||
#define f (cv_mem->cv_f)
|
||||
#define f_data (cv_mem->cv_f_data)
|
||||
#define uround (cv_mem->cv_uround)
|
||||
#define nst (cv_mem->cv_nst)
|
||||
#define tn (cv_mem->cv_tn)
|
||||
#define h (cv_mem->cv_h)
|
||||
#define gamma (cv_mem->cv_gamma)
|
||||
#define gammap (cv_mem->cv_gammap)
|
||||
#define gamrat (cv_mem->cv_gamrat)
|
||||
#define ewt (cv_mem->cv_ewt)
|
||||
#define nfe (cv_mem->cv_nfe)
|
||||
#define errfp (cv_mem->cv_errfp)
|
||||
#define iopt (cv_mem->cv_iopt)
|
||||
#define linit (cv_mem->cv_linit)
|
||||
#define lsetup (cv_mem->cv_lsetup)
|
||||
#define lsolve (cv_mem->cv_lsolve)
|
||||
#define lfree (cv_mem->cv_lfree)
|
||||
#define lmem (cv_mem->cv_lmem)
|
||||
|
||||
#define jac (cvdense_mem->d_jac)
|
||||
#define M (cvdense_mem->d_M)
|
||||
#define pivots (cvdense_mem->d_pivots)
|
||||
#define savedJ (cvdense_mem->d_savedJ)
|
||||
#define nstlj (cvdense_mem->d_nstlj)
|
||||
#define nje (cvdense_mem->d_nje)
|
||||
#define J_data (cvdense_mem->d_J_data)
|
||||
|
||||
|
||||
/*************** CVDense *********************************************
|
||||
|
||||
This routine initializes the memory record and sets various function
|
||||
fields specific to the dense linear solver module. CVDense sets the
|
||||
cv_linit, cv_lsetup, cv_lsolve, and cv_lfree fields in (*cvode_mem)
|
||||
to be CVDenseInit, CVDenseSetup, CVDenseSolve, and CVDenseFree,
|
||||
respectively. It allocates memory for a structure of type
|
||||
CVDenseMemRec and sets the cv_lmem field in (*cvode_mem) to the
|
||||
address of this structure. Finally, it sets d_J_data field in the
|
||||
CVDenseMemRec structure to be the input parameter jac_data and the
|
||||
d_jac field to be:
|
||||
|
||||
(1) the input parameter djac if djac != NULL or
|
||||
|
||||
(2) CVDenseDQJac if djac == NULL.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
void CVDense(void *cvode_mem, CVDenseJacFn djac, void *jac_data)
|
||||
{
|
||||
CVodeMem cv_mem;
|
||||
CVDenseMem cvdense_mem;
|
||||
|
||||
/* Return immediately if cvode_mem is NULL */
|
||||
cv_mem = (CVodeMem) cvode_mem;
|
||||
if (cv_mem == NULL) return; /* CVode reports this error */
|
||||
|
||||
/* Set four main function fields in cv_mem */
|
||||
linit = CVDenseInit;
|
||||
lsetup = CVDenseSetup;
|
||||
lsolve = CVDenseSolve;
|
||||
lfree = CVDenseFree;
|
||||
|
||||
/* Get memory for CVDenseMemRec */
|
||||
lmem = cvdense_mem = (CVDenseMem) malloc(sizeof(CVDenseMemRec));
|
||||
if (cvdense_mem == NULL) return; /* CVDenseInit reports this error */
|
||||
|
||||
/* Set Jacobian routine field to user's djac or CVDenseDQJac */
|
||||
if (djac == NULL) {
|
||||
jac = CVDenseDQJac;
|
||||
} else {
|
||||
jac = djac;
|
||||
}
|
||||
J_data = jac_data;
|
||||
}
|
||||
|
||||
/*************** CVDenseInit *****************************************
|
||||
|
||||
This routine initializes remaining memory specific to the dense
|
||||
linear solver. If any memory request fails, all memory previously
|
||||
allocated is freed, and an error message printed, before returning.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static int CVDenseInit(CVodeMem cv_mem, boole *setupNonNull)
|
||||
{
|
||||
CVDenseMem cvdense_mem;
|
||||
|
||||
cvdense_mem = (CVDenseMem) lmem;
|
||||
|
||||
/* Print error message and return if cvdense_mem is NULL */
|
||||
if (cvdense_mem == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
|
||||
/* Set flag setupNonNull = TRUE */
|
||||
*setupNonNull = TRUE;
|
||||
|
||||
/* Allocate memory for M, savedJ, and pivot array */
|
||||
|
||||
M = DenseAllocMat(N);
|
||||
if (M == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
savedJ = DenseAllocMat(N);
|
||||
if (savedJ == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
DenseFreeMat(M);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
pivots = DenseAllocPiv(N);
|
||||
if (pivots == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
DenseFreeMat(M);
|
||||
DenseFreeMat(savedJ);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
|
||||
/* Initialize nje and nstlj, and set workspace lengths */
|
||||
|
||||
nje = 0;
|
||||
if (iopt != NULL) {
|
||||
iopt[DENSE_NJE] = nje;
|
||||
iopt[DENSE_LRW] = 2*N*N;
|
||||
iopt[DENSE_LIW] = N;
|
||||
}
|
||||
nstlj = 0;
|
||||
|
||||
return(LINIT_OK);
|
||||
}
|
||||
|
||||
/*************** CVDenseSetup ****************************************
|
||||
|
||||
This routine does the setup operations for the dense linear solver.
|
||||
It makes a decision whether or not to call the Jacobian evaluation
|
||||
routine based on various state variables, and if not it uses the
|
||||
saved copy. In any case, it constructs the Newton matrix
|
||||
M = I - gamma*J, updates counters, and calls the dense LU
|
||||
factorization routine.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static int CVDenseSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
|
||||
N_Vector fpred, boole *jcurPtr, N_Vector vtemp1,
|
||||
N_Vector vtemp2, N_Vector vtemp3)
|
||||
{
|
||||
boole jbad, jok;
|
||||
real dgamma;
|
||||
integer ier;
|
||||
CVDenseMem cvdense_mem;
|
||||
|
||||
cvdense_mem = (CVDenseMem) lmem;
|
||||
|
||||
/* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
|
||||
|
||||
dgamma = ABS((gamma/gammap) - ONE);
|
||||
jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) ||
|
||||
((convfail == FAIL_BAD_J) && (dgamma < CVD_DGMAX)) ||
|
||||
(convfail == FAIL_OTHER);
|
||||
jok = !jbad;
|
||||
|
||||
if (jok) {
|
||||
/* If jok = TRUE, use saved copy of J */
|
||||
*jcurPtr = FALSE;
|
||||
DenseCopy(savedJ, M);
|
||||
} else {
|
||||
/* If jok = FALSE, call jac routine for new J value */
|
||||
nje++;
|
||||
if (iopt != NULL) iopt[DENSE_NJE] = nje;
|
||||
nstlj = nst;
|
||||
*jcurPtr = TRUE;
|
||||
DenseZero(M);
|
||||
jac(N, M, f, f_data, tn, ypred, fpred, ewt, h,
|
||||
uround, J_data, &nfe, vtemp1, vtemp2, vtemp3);
|
||||
DenseCopy(M, savedJ);
|
||||
}
|
||||
|
||||
/* Scale and add I to get M = I - gamma*J */
|
||||
DenseScale(-gamma, M);
|
||||
DenseAddI(M);
|
||||
|
||||
/* Do LU factorization of M */
|
||||
ier = DenseFactor(M, pivots);
|
||||
|
||||
/* Return 0 if the LU was complete; otherwise return 1 */
|
||||
if (ier > 0) return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*************** CVDenseSolve ****************************************
|
||||
|
||||
This routine handles the solve operation for the dense linear solver
|
||||
by calling the dense backsolve routine. The returned value is 0.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static int CVDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector ycur,
|
||||
N_Vector fcur)
|
||||
{
|
||||
CVDenseMem cvdense_mem;
|
||||
|
||||
cvdense_mem = (CVDenseMem) lmem;
|
||||
|
||||
DenseBacksolve(M, pivots, b);
|
||||
|
||||
/* If BDF, scale the correction to account for change in gamma */
|
||||
if ((lmm == BDF) && (gamrat != ONE)) {
|
||||
N_VScale(TWO/(ONE + gamrat), b, b);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*************** CVDenseFree *****************************************
|
||||
|
||||
This routine frees memory specific to the dense linear solver.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static void CVDenseFree(CVodeMem cv_mem)
|
||||
{
|
||||
CVDenseMem cvdense_mem;
|
||||
|
||||
cvdense_mem = (CVDenseMem) lmem;
|
||||
|
||||
DenseFreeMat(M);
|
||||
DenseFreeMat(savedJ);
|
||||
DenseFreePiv(pivots);
|
||||
free(lmem);
|
||||
}
|
||||
|
|
@ -1,292 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : cvdiag.c *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 4 May 1998 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the implementation file for the CVODE diagonal linear *
|
||||
* solver, CVDIAG. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "cvdiag.h"
|
||||
#include "cvode.h"
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
|
||||
|
||||
/* Error Messages */
|
||||
|
||||
#define CVDIAG_INIT "CVDiagInit-- "
|
||||
|
||||
#define MSG_MEM_FAIL CVDIAG_INIT "A memory request failed.\n\n"
|
||||
|
||||
|
||||
/* Other Constants */
|
||||
|
||||
#define FRACT RCONST(0.1)
|
||||
#define ONE RCONST(1.0)
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Types : CVDiagMemRec, CVDiagMem *
|
||||
*----------------------------------------------------------------*
|
||||
* The type CVDiagMem is pointer to a CVDiagMemRec. This *
|
||||
* structure contains CVDiag solver-specific data. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
||||
real di_gammasv; /* gammasv = gamma at the last call to setup */
|
||||
/* or solve */
|
||||
|
||||
N_Vector di_M; /* M = (I - gamma J)^{-1} , gamma = h / l1 */
|
||||
|
||||
N_Vector di_bit; /* temporary storage vector */
|
||||
|
||||
N_Vector di_bitcomp; /* temporary storage vector */
|
||||
|
||||
} CVDiagMemRec, *CVDiagMem;
|
||||
|
||||
|
||||
/* CVDIAG linit, lsetup, lsolve, and lfree routines */
|
||||
|
||||
static int CVDiagInit(CVodeMem cv_mem, boole *setupNonNull);
|
||||
|
||||
static int CVDiagSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
|
||||
N_Vector fpred, boole *jcurPtr, N_Vector vtemp1,
|
||||
N_Vector vtemp2, N_Vector vtemp3);
|
||||
|
||||
static int CVDiagSolve(CVodeMem cv_mem, N_Vector b, N_Vector ycur,
|
||||
N_Vector fcur);
|
||||
|
||||
static void CVDiagFree(CVodeMem cv_mem);
|
||||
|
||||
|
||||
/* Readability Replacements */
|
||||
|
||||
#define N (cv_mem->cv_N)
|
||||
#define f (cv_mem->cv_f)
|
||||
#define f_data (cv_mem->cv_f_data)
|
||||
#define uround (cv_mem->cv_uround)
|
||||
#define tn (cv_mem->cv_tn)
|
||||
#define h (cv_mem->cv_h)
|
||||
#define rl1 (cv_mem->cv_rl1)
|
||||
#define gamma (cv_mem->cv_gamma)
|
||||
#define ewt (cv_mem->cv_ewt)
|
||||
#define nfe (cv_mem->cv_nfe)
|
||||
#define errfp (cv_mem->cv_errfp)
|
||||
#define iopt (cv_mem->cv_iopt)
|
||||
#define zn (cv_mem->cv_zn)
|
||||
#define linit (cv_mem->cv_linit)
|
||||
#define lsetup (cv_mem->cv_lsetup)
|
||||
#define lsolve (cv_mem->cv_lsolve)
|
||||
#define lfree (cv_mem->cv_lfree)
|
||||
#define lmem (cv_mem->cv_lmem)
|
||||
#define machenv (cv_mem->cv_machenv)
|
||||
|
||||
#define gammasv (cvdiag_mem->di_gammasv)
|
||||
#define M (cvdiag_mem->di_M)
|
||||
#define bit (cvdiag_mem->di_bit)
|
||||
#define bitcomp (cvdiag_mem->di_bitcomp)
|
||||
|
||||
|
||||
|
||||
/*************** CVDiag **********************************************
|
||||
|
||||
This routine initializes the memory record and sets various function
|
||||
fields specific to the diagonal linear solver module. CVDiag sets the
|
||||
cv_linit, cv_lsetup, cv_lsolve, and cv_lfree fields in (*cvode_mem)
|
||||
to be CVDiagInit, CVDiagSetup, CVDiagSolve, and CVDiagFree,
|
||||
respectively. It allocates memory for a structure of type
|
||||
CVDiagMemRec and sets the cv_lmem field in (*cvode_mem) to the
|
||||
address of this structure.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
void CVDiag(void *cvode_mem)
|
||||
{
|
||||
CVodeMem cv_mem;
|
||||
CVDiagMem cvdiag_mem;
|
||||
|
||||
/* Return immediately if cvode_mem is NULL */
|
||||
cv_mem = (CVodeMem) cvode_mem;
|
||||
if (cv_mem == NULL) return; /* CVode reports this error */
|
||||
|
||||
/* Set four main function fields in cv_mem */
|
||||
linit = CVDiagInit;
|
||||
lsetup = CVDiagSetup;
|
||||
lsolve = CVDiagSolve;
|
||||
lfree = CVDiagFree;
|
||||
|
||||
/* Get memory for CVDiagMemRec */
|
||||
lmem = cvdiag_mem = (CVDiagMem) malloc(sizeof(CVDiagMemRec));
|
||||
if (cvdiag_mem == NULL) return; /* CVDiagInit reports this error */
|
||||
}
|
||||
|
||||
/*************** CVDiagInit ******************************************
|
||||
|
||||
This routine initializes remaining memory specific to the diagonal
|
||||
linear solver. If any memory request fails, all memory previously
|
||||
allocated is freed, and an error message printed, before returning.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static int CVDiagInit(CVodeMem cv_mem, boole *setupNonNull)
|
||||
{
|
||||
CVDiagMem cvdiag_mem;
|
||||
|
||||
cvdiag_mem = (CVDiagMem) lmem;
|
||||
|
||||
/* Print error message and return if cvdiag_mem is NULL */
|
||||
if (cvdiag_mem == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
|
||||
/* Set flag setupNonNull = TRUE */
|
||||
*setupNonNull = TRUE;
|
||||
|
||||
/* Allocate memory for M, bit, and bitcomp */
|
||||
|
||||
M = N_VNew(N, machenv);
|
||||
if (M == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
bit = N_VNew(N, machenv);
|
||||
if (bit == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
N_VFree(M);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
bitcomp = N_VNew(N, machenv);
|
||||
if (bitcomp == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
N_VFree(M);
|
||||
N_VFree(bit);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
|
||||
/* Set workspace lengths */
|
||||
if (iopt != NULL) {
|
||||
iopt[DIAG_LRW] = N*3;
|
||||
iopt[DIAG_LIW] = 0;
|
||||
}
|
||||
|
||||
return(LINIT_OK);
|
||||
}
|
||||
|
||||
/*************** CVDiagSetup *****************************************
|
||||
|
||||
This routine does the setup operations for the diagonal linear
|
||||
solver. It constructs a diagonal approximation to the Newton matrix
|
||||
M = I - gamma*J, updates counters, and inverts M.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static int CVDiagSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
|
||||
N_Vector fpred, boole *jcurPtr, N_Vector vtemp1,
|
||||
N_Vector vtemp2, N_Vector vtemp3)
|
||||
{
|
||||
real r;
|
||||
N_Vector ftemp, y;
|
||||
boole invOK;
|
||||
CVDiagMem cvdiag_mem;
|
||||
|
||||
cvdiag_mem = (CVDiagMem) lmem;
|
||||
|
||||
/* Rename work vectors for use as temporary values of y and f */
|
||||
ftemp = vtemp1;
|
||||
y = vtemp2;
|
||||
|
||||
/* Form y with perturbation = FRACT*(func. iter. correction) */
|
||||
r = FRACT * rl1;
|
||||
N_VLinearSum(h, fpred, -ONE, zn[1], ftemp);
|
||||
N_VLinearSum(r, ftemp, ONE, ypred, y);
|
||||
|
||||
/* Evaluate f at perturbed y */
|
||||
f(N, tn, y, M, f_data);
|
||||
nfe++;
|
||||
|
||||
/* Construct M = I - gamma*J with J = diag(deltaf_i/deltay_i) */
|
||||
N_VLinearSum(ONE, M, -ONE, fpred, M);
|
||||
N_VLinearSum(FRACT, ftemp, -h, M, M);
|
||||
N_VProd(ftemp, ewt, y);
|
||||
/* Protect against deltay_i being at roundoff level */
|
||||
N_VCompare(uround, y, bit);
|
||||
N_VAddConst(bit, -ONE, bitcomp);
|
||||
N_VProd(ftemp, bit, y);
|
||||
N_VLinearSum(FRACT, y, -ONE, bitcomp, y);
|
||||
N_VDiv(M, y, M);
|
||||
N_VProd(M, bit, M);
|
||||
N_VLinearSum(ONE, M, -ONE, bitcomp, M);
|
||||
|
||||
/* Invert M with test for zero components */
|
||||
invOK = N_VInvTest(M, M);
|
||||
if (!invOK) return(1);
|
||||
|
||||
/* Set jcur = TRUE, save gamma in gammasv, and return */
|
||||
*jcurPtr = TRUE;
|
||||
gammasv = gamma;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*************** CVDiagSolve *****************************************
|
||||
|
||||
This routine performs the solve operation for the diagonal linear
|
||||
solver. If necessary it first updates gamma in M = I - gamma*J.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static int CVDiagSolve(CVodeMem cv_mem, N_Vector b, N_Vector ycur,
|
||||
N_Vector fcur)
|
||||
{
|
||||
boole invOK;
|
||||
real r;
|
||||
CVDiagMem cvdiag_mem;
|
||||
|
||||
cvdiag_mem = (CVDiagMem) lmem;
|
||||
|
||||
/* If gamma has changed, update factor in M, and save gamma value */
|
||||
|
||||
if (gammasv != gamma) {
|
||||
r = gamma / gammasv;
|
||||
N_VInv(M, M);
|
||||
N_VAddConst(M, -ONE, M);
|
||||
N_VScale(r, M, M);
|
||||
N_VAddConst(M, ONE, M);
|
||||
invOK = N_VInvTest(M, M);
|
||||
if (!invOK) return (1);
|
||||
|
||||
gammasv = gamma;
|
||||
}
|
||||
|
||||
/* Apply M-inverse to b */
|
||||
N_VProd(b, M, b);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*************** CVDiagFree ******************************************
|
||||
|
||||
This routine frees memory specific to the diagonal linear solver.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static void CVDiagFree(CVodeMem cv_mem)
|
||||
{
|
||||
CVDiagMem cvdiag_mem;
|
||||
|
||||
cvdiag_mem = (CVDiagMem) lmem;
|
||||
|
||||
N_VFree(M);
|
||||
N_VFree(bit);
|
||||
N_VFree(bitcomp);
|
||||
free(lmem);
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,499 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : cvspgmr.c *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 25 February 2000 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the implementation file for the CVODE scaled, *
|
||||
* preconditioned GMRES linear solver, CVSPGMR. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "cvspgmr.h"
|
||||
#include "cvode.h"
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
#include "llnlmath.h"
|
||||
#include "iterativ.h"
|
||||
#include "spgmr.h"
|
||||
|
||||
|
||||
/* Error Messages */
|
||||
|
||||
#define CVSPGMR_INIT "CVSpgmrInit-- "
|
||||
|
||||
#define MSG_MEM_FAIL CVSPGMR_INIT "A memory request failed.\n\n"
|
||||
|
||||
#define MSG_BAD_PRETYPE_1 CVSPGMR_INIT "pretype=%d illegal.\n"
|
||||
#define MSG_BAD_PRETYPE_2 "The legal values are NONE=%d, LEFT=%d, "
|
||||
#define MSG_BAD_PRETYPE_3 "RIGHT=%d, and BOTH=%d.\n\n"
|
||||
#define MSG_BAD_PRETYPE MSG_BAD_PRETYPE_1 MSG_BAD_PRETYPE_2 MSG_BAD_PRETYPE_3
|
||||
|
||||
#define MSG_PSOLVE_REQ_1 CVSPGMR_INIT "pretype!=NONE, but PSOLVE=NULL is "
|
||||
#define MSG_PSOLVE_REQ_2 "illegal.\n\n"
|
||||
#define MSG_PSOLVE_REQ MSG_PSOLVE_REQ_1 MSG_PSOLVE_REQ_2
|
||||
|
||||
#define MSG_BAD_GSTYPE_1 CVSPGMR_INIT "gstype=%d illegal.\n"
|
||||
#define MSG_BAD_GSTYPE_2 "The legal values are MODIFIED_GS=%d and "
|
||||
#define MSG_BAD_GSTYPE_3 "CLASSICAL_GS=%d.\n\n"
|
||||
#define MSG_BAD_GSTYPE MSG_BAD_GSTYPE_1 MSG_BAD_GSTYPE_2 MSG_BAD_GSTYPE_3
|
||||
|
||||
/* Other Constants */
|
||||
|
||||
#define ZERO RCONST(0.0)
|
||||
#define ONE RCONST(1.0)
|
||||
|
||||
/******************************************************************
|
||||
* *
|
||||
* Types : CVSpgmrMemRec, CVSpgmrMem *
|
||||
*----------------------------------------------------------------*
|
||||
* The type CVSpgmrMem is pointer to a CVSpgmrMemRec. This *
|
||||
* structure contains CVSpgmr solver-specific data. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
typedef struct {
|
||||
|
||||
int g_pretype; /* type of preconditioning */
|
||||
int g_gstype; /* type of Gram-Schmidt orthogonalization */
|
||||
real g_sqrtN; /* sqrt(N) */
|
||||
real g_delt; /* delt = user specified or DELT_DEFAULT */
|
||||
real g_deltar; /* deltar = delt * tq4 */
|
||||
real g_delta; /* delta = deltar * sqrtN */
|
||||
int g_maxl; /* maxl = maximum dimension of the Krylov space */
|
||||
|
||||
long int g_nstlpre; /* value of nst at the last precond call */
|
||||
long int g_npe; /* npe = total number of precond calls */
|
||||
long int g_nli; /* nli = total number of linear iterations */
|
||||
long int g_nps; /* nps = total number of psolve calls */
|
||||
long int g_ncfl; /* ncfl = total number of convergence failures */
|
||||
|
||||
N_Vector g_ytemp; /* temp vector used by CVAtimesDQ */
|
||||
N_Vector g_x; /* temp vector used by CVSpgmrSolve */
|
||||
N_Vector g_ycur; /* CVODE current y vector in Newton Iteration */
|
||||
N_Vector g_fcur; /* fcur = f(tn, ycur) */
|
||||
|
||||
CVSpgmrPrecondFn g_precond; /* precond = user-supplied routine to */
|
||||
/* compute a preconditioner */
|
||||
|
||||
CVSpgmrPSolveFn g_psolve; /* psolve = user-supplied routine to */
|
||||
/* solve preconditioner linear system */
|
||||
|
||||
void *g_P_data; /* P_data passed to psolve and precond */
|
||||
SpgmrMem g_spgmr_mem; /* spgmr_mem is memory used by the */
|
||||
/* generic Spgmr solver */
|
||||
|
||||
} CVSpgmrMemRec, *CVSpgmrMem;
|
||||
|
||||
|
||||
/* CVSPGMR linit, lsetup, lsolve, and lfree routines */
|
||||
|
||||
static int CVSpgmrInit(CVodeMem cv_mem, boole *setupNonNull);
|
||||
|
||||
static int CVSpgmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
|
||||
N_Vector fpred, boole *jcurPtr, N_Vector vtemp1,
|
||||
N_Vector vtemp2, N_Vector vtemp3);
|
||||
|
||||
static int CVSpgmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector ycur,
|
||||
N_Vector fcur);
|
||||
|
||||
static void CVSpgmrFree(CVodeMem cv_mem);
|
||||
|
||||
/* CVSPGMR Atimes and PSolve routines called by generic SPGMR solver */
|
||||
|
||||
static int CVSpgmrAtimesDQ(void *cv_mem, N_Vector v, N_Vector z);
|
||||
|
||||
static int CVSpgmrPSolve(void *cv_mem, N_Vector r, N_Vector z, int lr);
|
||||
|
||||
|
||||
/* Readability Replacements */
|
||||
|
||||
#define N (cv_mem->cv_N)
|
||||
#define uround (cv_mem->cv_uround)
|
||||
#define tq (cv_mem->cv_tq)
|
||||
#define nst (cv_mem->cv_nst)
|
||||
#define tn (cv_mem->cv_tn)
|
||||
#define h (cv_mem->cv_h)
|
||||
#define gamma (cv_mem->cv_gamma)
|
||||
#define gammap (cv_mem->cv_gammap)
|
||||
#define nfe (cv_mem->cv_nfe)
|
||||
#define f (cv_mem->cv_f)
|
||||
#define f_data (cv_mem->cv_f_data)
|
||||
#define ewt (cv_mem->cv_ewt)
|
||||
#define errfp (cv_mem->cv_errfp)
|
||||
#define mnewt (cv_mem->cv_mnewt)
|
||||
#define iopt (cv_mem->cv_iopt)
|
||||
#define ropt (cv_mem->cv_ropt)
|
||||
#define linit (cv_mem->cv_linit)
|
||||
#define lsetup (cv_mem->cv_lsetup)
|
||||
#define lsolve (cv_mem->cv_lsolve)
|
||||
#define lfree (cv_mem->cv_lfree)
|
||||
#define lmem (cv_mem->cv_lmem)
|
||||
#define machenv (cv_mem->cv_machenv)
|
||||
|
||||
#define sqrtN (cvspgmr_mem->g_sqrtN)
|
||||
#define ytemp (cvspgmr_mem->g_ytemp)
|
||||
#define x (cvspgmr_mem->g_x)
|
||||
#define ycur (cvspgmr_mem->g_ycur)
|
||||
#define fcur (cvspgmr_mem->g_fcur)
|
||||
#define delta (cvspgmr_mem->g_delta)
|
||||
#define deltar (cvspgmr_mem->g_deltar)
|
||||
#define npe (cvspgmr_mem->g_npe)
|
||||
#define nli (cvspgmr_mem->g_nli)
|
||||
#define nps (cvspgmr_mem->g_nps)
|
||||
#define ncfl (cvspgmr_mem->g_ncfl)
|
||||
#define nstlpre (cvspgmr_mem->g_nstlpre)
|
||||
#define spgmr_mem (cvspgmr_mem->g_spgmr_mem)
|
||||
|
||||
|
||||
/*************** CVSpgmr *********************************************
|
||||
|
||||
This routine initializes the memory record and sets various function
|
||||
fields specific to the Spgmr linear solver module. CVSpgmr sets the
|
||||
cv_linit, cv_lsetup, cv_lsolve, and cv_lfree fields in (*cvode_mem)
|
||||
to be CVSpgmrInit, CVSpgmrSetup, CVSpgmrSolve, and CVSpgmrFree,
|
||||
respectively. It allocates memory for a structure of type
|
||||
CVSpgmrMemRec and sets the cv_lmem field in (*cvode_mem) to the
|
||||
address of this structure. CVSpgmr sets the following fields in the
|
||||
CVSpgmrMemRec structure:
|
||||
|
||||
g_pretype = pretype
|
||||
g_maxl = MIN(N,CVSPGMR_MAXL) if maxl <= 0
|
||||
= maxl if maxl > 0
|
||||
g_delt = CVSPGMR_DELT if delt == 0.0
|
||||
= delt if delt != 0.0
|
||||
g_P_data = P_data
|
||||
g_precond = precond
|
||||
g_psolve = psolve
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
void CVSpgmr(void *cvode_mem, int pretype, int gstype, int maxl, real delt,
|
||||
CVSpgmrPrecondFn precond, CVSpgmrPSolveFn psolve, void *P_data)
|
||||
|
||||
{
|
||||
CVodeMem cv_mem;
|
||||
CVSpgmrMem cvspgmr_mem;
|
||||
|
||||
/* Return immediately if cvode_mem is NULL */
|
||||
cv_mem = (CVodeMem) cvode_mem;
|
||||
if (cv_mem == NULL) return; /* CVode reports this error */
|
||||
|
||||
/* Set four main function fields in cv_mem */
|
||||
linit = CVSpgmrInit;
|
||||
lsetup = CVSpgmrSetup;
|
||||
lsolve = CVSpgmrSolve;
|
||||
lfree = CVSpgmrFree;
|
||||
|
||||
/* Get memory for CVSpgmrMemRec */
|
||||
lmem = cvspgmr_mem = (CVSpgmrMem) malloc(sizeof(CVSpgmrMemRec));
|
||||
if (cvspgmr_mem == NULL) return; /* CVSpgmrInit reports this error */
|
||||
|
||||
/* Set Spgmr parameters that have been passed in call sequence */
|
||||
cvspgmr_mem->g_pretype = pretype;
|
||||
cvspgmr_mem->g_gstype = gstype;
|
||||
cvspgmr_mem->g_maxl = (maxl <= 0) ? MIN(CVSPGMR_MAXL, N) : maxl;
|
||||
cvspgmr_mem->g_delt = (delt == ZERO) ? CVSPGMR_DELT : delt;
|
||||
cvspgmr_mem->g_P_data = P_data;
|
||||
cvspgmr_mem->g_precond = precond;
|
||||
cvspgmr_mem->g_psolve = psolve;
|
||||
}
|
||||
|
||||
|
||||
/* Additional readability Replacements */
|
||||
|
||||
#define pretype (cvspgmr_mem->g_pretype)
|
||||
#define gstype (cvspgmr_mem->g_gstype)
|
||||
#define delt (cvspgmr_mem->g_delt)
|
||||
#define maxl (cvspgmr_mem->g_maxl)
|
||||
#define psolve (cvspgmr_mem->g_psolve)
|
||||
#define precond (cvspgmr_mem->g_precond)
|
||||
#define P_data (cvspgmr_mem->g_P_data)
|
||||
|
||||
|
||||
/*************** CVSpgmrInit *****************************************
|
||||
|
||||
This routine initializes remaining memory specific to the Spgmr
|
||||
linear solver. If any memory request fails, all memory previously
|
||||
allocated is freed, and an error message printed, before returning.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static int CVSpgmrInit(CVodeMem cv_mem, boole *setupNonNull)
|
||||
{
|
||||
CVSpgmrMem cvspgmr_mem;
|
||||
|
||||
cvspgmr_mem = (CVSpgmrMem) lmem;
|
||||
|
||||
/* Print error message and return if cvspgmr_mem is NULL */
|
||||
if (cvspgmr_mem == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
|
||||
/* Check for legal pretype, precond, and psolve */
|
||||
if ((pretype != NONE) && (pretype != LEFT) &&
|
||||
(pretype != RIGHT) && (pretype != BOTH)) {
|
||||
fprintf(errfp, MSG_BAD_PRETYPE, pretype, NONE, LEFT, RIGHT, BOTH);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
if ((pretype != NONE) && (psolve == NULL)) {
|
||||
fprintf(errfp, MSG_PSOLVE_REQ);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
|
||||
/* Check for legal gstype */
|
||||
if ((gstype != MODIFIED_GS) && (gstype != CLASSICAL_GS)) {
|
||||
fprintf(errfp, MSG_BAD_GSTYPE, gstype, MODIFIED_GS, CLASSICAL_GS);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
|
||||
/* Allocate memory for ytemp and x */
|
||||
ytemp = N_VNew(N, machenv);
|
||||
if (ytemp == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
x = N_VNew(N, machenv);
|
||||
if (x == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
N_VFree(ytemp);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
|
||||
/* Call SpgmrMalloc to allocate workspace for Spgmr */
|
||||
spgmr_mem = SpgmrMalloc(N, maxl, machenv);
|
||||
if (spgmr_mem == NULL) {
|
||||
fprintf(errfp, MSG_MEM_FAIL);
|
||||
N_VFree(ytemp);
|
||||
N_VFree(x);
|
||||
return(LINIT_ERR);
|
||||
}
|
||||
|
||||
/* Initialize sqrtN and counters, and set workspace lengths */
|
||||
|
||||
sqrtN = RSqrt(N);
|
||||
npe = nli = nps = ncfl = nstlpre = 0;
|
||||
|
||||
if (iopt != NULL) {
|
||||
iopt[SPGMR_NPE] = npe;
|
||||
iopt[SPGMR_NLI] = nli;
|
||||
iopt[SPGMR_NPS] = nps;
|
||||
iopt[SPGMR_NCFL] = ncfl;
|
||||
iopt[SPGMR_LRW] = N*(maxl + 5) + maxl*(maxl + 4) + 1;
|
||||
iopt[SPGMR_LIW] = 0;
|
||||
}
|
||||
|
||||
/* Set setupNonNull to TRUE iff there is preconditioning */
|
||||
/* (pretype != NONE) and there is a preconditioning setup phase */
|
||||
/* (precond != NULL) */
|
||||
*setupNonNull = (pretype != NONE) && (precond != NULL);
|
||||
|
||||
return(LINIT_OK);
|
||||
}
|
||||
|
||||
/*************** CVSpgmrSetup ****************************************
|
||||
|
||||
This routine does the setup operations for the Spgmr linear solver.
|
||||
It makes a decision as to whether or not to signal for re-evaluation
|
||||
of Jacobian data in the precond routine, based on various state
|
||||
variables, then it calls precond. If we signal for re-evaluation,
|
||||
then we reset jcur = *jcurPtr to TRUE, regardless of the precond output.
|
||||
In any case, if jcur == TRUE, we increment npe and save nst in nstlpre.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static int CVSpgmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
|
||||
N_Vector fpred, boole *jcurPtr, N_Vector vtemp1,
|
||||
N_Vector vtemp2, N_Vector vtemp3)
|
||||
{
|
||||
boole jbad, jok;
|
||||
real dgamma;
|
||||
int ier;
|
||||
CVSpgmrMem cvspgmr_mem;
|
||||
|
||||
cvspgmr_mem = (CVSpgmrMem) lmem;
|
||||
|
||||
/* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
|
||||
dgamma = ABS((gamma/gammap) - ONE);
|
||||
jbad = (nst == 0) || (nst > nstlpre + CVSPGMR_MSBPRE) ||
|
||||
((convfail == FAIL_BAD_J) && (dgamma < CVSPGMR_DGMAX)) ||
|
||||
(convfail == FAIL_OTHER);
|
||||
*jcurPtr = jbad;
|
||||
jok = !jbad;
|
||||
|
||||
/* Call precond routine and possibly reset jcur */
|
||||
ier = precond(N, tn, ypred, fpred, jok, jcurPtr, gamma, ewt, h,
|
||||
uround, &nfe, P_data, vtemp1, vtemp2, vtemp3);
|
||||
if (jbad) *jcurPtr = TRUE;
|
||||
|
||||
/* If jcur = TRUE, increment npe and save nst value */
|
||||
if (*jcurPtr) {
|
||||
npe++;
|
||||
nstlpre = nst;
|
||||
}
|
||||
|
||||
/* Set npe, and return the same value ier that precond returned */
|
||||
if (iopt != NULL) iopt[SPGMR_NPE] = npe;
|
||||
return(ier);
|
||||
}
|
||||
|
||||
/*************** CVSpgmrSolve ****************************************
|
||||
|
||||
This routine handles the call to the generic solver SpgmrSolve
|
||||
for the solution of the linear system Ax = b with the SPGMR method,
|
||||
without restarts. The solution x is returned in the vector b.
|
||||
|
||||
If the WRMS norm of b is small, we return x = b (if this is the first
|
||||
Newton iteration) or x = 0 (if a later Newton iteration).
|
||||
|
||||
Otherwise, we set the tolerance parameter and initial guess (x = 0),
|
||||
call SpgmrSolve, and copy the solution x into b. The x-scaling and
|
||||
b-scaling arrays are both equal to ewt, and no restarts are allowed.
|
||||
|
||||
The counters nli, nps, and ncfl are incremented, and the return value
|
||||
is set according to the success of SpgmrSolve. The success flag is
|
||||
returned if SpgmrSolve converged, or if this is the first Newton
|
||||
iteration and the residual norm was reduced below its initial value.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static int CVSpgmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector ynow,
|
||||
N_Vector fnow)
|
||||
{
|
||||
real bnorm, res_norm;
|
||||
CVSpgmrMem cvspgmr_mem;
|
||||
int nli_inc, nps_inc, ier;
|
||||
|
||||
cvspgmr_mem = (CVSpgmrMem) lmem;
|
||||
|
||||
/* Test norm(b); if small, return x = 0 or x = b */
|
||||
deltar = delt*tq[4];
|
||||
bnorm = N_VWrmsNorm(b, ewt);
|
||||
if (bnorm <= deltar) {
|
||||
if (mnewt > 0) N_VConst(ZERO, b);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Set vectors ycur and fcur for use by the Atimes and Psolve routines */
|
||||
ycur = ynow;
|
||||
fcur = fnow;
|
||||
|
||||
/* Set inputs delta and initial guess x = 0 to SpgmrSolve */
|
||||
delta = deltar * sqrtN;
|
||||
N_VConst(ZERO, x);
|
||||
|
||||
/* Call SpgmrSolve and copy x to b */
|
||||
ier = SpgmrSolve(spgmr_mem, cv_mem, x, b, pretype, gstype, delta, 0,
|
||||
cv_mem, ewt, ewt, CVSpgmrAtimesDQ, CVSpgmrPSolve,
|
||||
&res_norm, &nli_inc, &nps_inc);
|
||||
N_VScale(ONE, x, b);
|
||||
|
||||
/* Increment counters nli, nps, and ncfl */
|
||||
nli += nli_inc;
|
||||
nps += nps_inc;
|
||||
if (iopt != NULL) {
|
||||
iopt[SPGMR_NLI] = nli;
|
||||
iopt[SPGMR_NPS] = nps;
|
||||
}
|
||||
if (ier != 0) {
|
||||
ncfl++;
|
||||
if (iopt != NULL) iopt[SPGMR_NCFL] = ncfl;
|
||||
}
|
||||
|
||||
/* Set return value to -1, 0, or 1 */
|
||||
if (ier < 0) return(-1);
|
||||
if ((ier == SPGMR_SUCCESS) ||
|
||||
((ier == SPGMR_RES_REDUCED) && (mnewt == 0)))
|
||||
return(0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*************** CVSpgmrFree *****************************************
|
||||
|
||||
This routine frees memory specific to the Spgmr linear solver.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static void CVSpgmrFree(CVodeMem cv_mem)
|
||||
{
|
||||
CVSpgmrMem cvspgmr_mem;
|
||||
|
||||
cvspgmr_mem = (CVSpgmrMem) lmem;
|
||||
|
||||
N_VFree(ytemp);
|
||||
N_VFree(x);
|
||||
SpgmrFree(spgmr_mem);
|
||||
free(lmem);
|
||||
}
|
||||
|
||||
/*************** CVSpgmrAtimesDQ *************************************
|
||||
|
||||
This routine generates the matrix-vector product z = Mv, where
|
||||
M = I - gamma*J, by using a difference quotient approximation to
|
||||
the product Jv. The approximation is Jv = rho[f(y + v/rho) - f(y)],
|
||||
where rho = (WRMS norm of v), i.e. the WRMS norm of v/rho is 1.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static int CVSpgmrAtimesDQ(void *cvode_mem, N_Vector v, N_Vector z)
|
||||
{
|
||||
real rho;
|
||||
CVodeMem cv_mem;
|
||||
CVSpgmrMem cvspgmr_mem;
|
||||
|
||||
cv_mem = (CVodeMem) cvode_mem;
|
||||
cvspgmr_mem = (CVSpgmrMem) lmem;
|
||||
|
||||
/* If rho = norm(v) is 0, return z = 0 */
|
||||
rho = N_VWrmsNorm(v, ewt);
|
||||
if (rho == ZERO) {
|
||||
N_VConst(ZERO, z);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Set ytemp = ycur + (1/rho) v */
|
||||
N_VLinearSum(ONE/rho, v, ONE, ycur, ytemp);
|
||||
|
||||
/* Set z = f(tn, ytemp) */
|
||||
f(N, tn, ytemp, z, f_data);
|
||||
nfe++;
|
||||
|
||||
/* Replace z by v - (gamma*rho)(z - fcur) */
|
||||
N_VLinearSum(ONE, z, -ONE, fcur, z);
|
||||
N_VLinearSum(-gamma*rho, z, ONE, v, z);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*************** CVSpgmrPSolve ***************************************
|
||||
|
||||
This routine interfaces between the generic SpgmrSolve routine and
|
||||
the user's psolve routine. It passes to psolve all required state
|
||||
information from cvode_mem. Its return value is the same as that
|
||||
returned by psolve. Note that the generic SPGMR solver guarantees
|
||||
that CVSpgmrPSolve will not be called in the case in which
|
||||
preconditioning is not done. This is the only case in which the
|
||||
user's psolve routine is allowed to be NULL.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
static int CVSpgmrPSolve(void *cvode_mem, N_Vector r, N_Vector z, int lr)
|
||||
{
|
||||
CVodeMem cv_mem;
|
||||
CVSpgmrMem cvspgmr_mem;
|
||||
int ier;
|
||||
|
||||
cv_mem = (CVodeMem) cvode_mem;
|
||||
cvspgmr_mem = (CVSpgmrMem)lmem;
|
||||
|
||||
ier = psolve(N, tn, ycur, fcur, ytemp, gamma, ewt, delta, &nfe, r,
|
||||
lr, P_data, z);
|
||||
/* This call is counted in nps within the CVSpgmrSolve routine */
|
||||
|
||||
return(ier);
|
||||
}
|
||||
|
||||
|
|
@ -1,311 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : dense.c *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 25 February 2000 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the implementation file for a generic DENSE linear *
|
||||
* solver package. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "dense.h"
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
#include "llnlmath.h"
|
||||
|
||||
|
||||
#define ZERO RCONST(0.0)
|
||||
#define ONE RCONST(1.0)
|
||||
|
||||
|
||||
/* Implementation */
|
||||
|
||||
|
||||
DenseMat DenseAllocMat(integer N)
|
||||
{
|
||||
DenseMat A;
|
||||
|
||||
if (N <= 0) return(NULL);
|
||||
|
||||
A = (DenseMat) malloc(sizeof *A);
|
||||
if (A==NULL) return (NULL);
|
||||
|
||||
A->data = denalloc(N);
|
||||
if (A->data == NULL) {
|
||||
free(A);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
A->size = N;
|
||||
|
||||
return(A);
|
||||
}
|
||||
|
||||
|
||||
integer *DenseAllocPiv(integer N)
|
||||
{
|
||||
if (N <= 0) return(NULL);
|
||||
|
||||
return((integer *) malloc(N * sizeof(integer)));
|
||||
}
|
||||
|
||||
|
||||
integer DenseFactor(DenseMat A, integer *p)
|
||||
{
|
||||
return(gefa(A->data, A->size, p));
|
||||
}
|
||||
|
||||
|
||||
void DenseBacksolve(DenseMat A, integer *p, N_Vector b)
|
||||
{
|
||||
gesl(A->data, A->size, p, N_VDATA(b));
|
||||
}
|
||||
|
||||
|
||||
void DenseZero(DenseMat A)
|
||||
{
|
||||
denzero(A->data, A->size);
|
||||
}
|
||||
|
||||
void DenseCopy(DenseMat A, DenseMat B)
|
||||
{
|
||||
dencopy(A->data, B->data, A->size);
|
||||
}
|
||||
|
||||
void DenseScale(real c, DenseMat A)
|
||||
{
|
||||
denscale(c, A->data, A->size);
|
||||
}
|
||||
|
||||
void DenseAddI(DenseMat A)
|
||||
{
|
||||
denaddI(A->data, A->size);
|
||||
}
|
||||
|
||||
void DenseFreeMat(DenseMat A)
|
||||
{
|
||||
denfree(A->data);
|
||||
free(A);
|
||||
}
|
||||
|
||||
void DenseFreePiv(integer *p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
void DensePrint(DenseMat A)
|
||||
{
|
||||
denprint(A->data, A->size);
|
||||
}
|
||||
|
||||
|
||||
real **denalloc(integer n)
|
||||
{
|
||||
integer j;
|
||||
real **a;
|
||||
|
||||
if (n <= 0) return(NULL);
|
||||
|
||||
a = (real **) malloc(n * sizeof(real *));
|
||||
if (a == NULL) return(NULL);
|
||||
|
||||
a[0] = (real *) malloc(n * n * sizeof(real));
|
||||
if (a[0] == NULL) {
|
||||
free(a);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
for (j=1; j < n; j++) a[j] = a[0] + j * n;
|
||||
|
||||
return(a);
|
||||
}
|
||||
|
||||
integer *denallocpiv(integer n)
|
||||
{
|
||||
if (n <= 0) return(NULL);
|
||||
|
||||
return((integer *) malloc(n * sizeof(integer)));
|
||||
}
|
||||
|
||||
integer gefa(real **a, integer n, integer *p)
|
||||
{
|
||||
integer i, j, k, l;
|
||||
real *col_j, *col_k, *diag_k;
|
||||
real temp, mult, a_kj;
|
||||
boole swap;
|
||||
|
||||
/* k = elimination step number */
|
||||
|
||||
for (k=0; k < n-1; k++, p++) {
|
||||
|
||||
col_k = a[k];
|
||||
diag_k = col_k + k;
|
||||
|
||||
/* find l = pivot row number */
|
||||
|
||||
l=k;
|
||||
for (i=k+1; i < n; i++)
|
||||
if (ABS(col_k[i]) > ABS(col_k[l])) l=i;
|
||||
*p = l;
|
||||
|
||||
/* check for zero pivot element */
|
||||
|
||||
if (col_k[l] == ZERO) return(k+1);
|
||||
|
||||
/* swap a(l,k) and a(k,k) if necessary */
|
||||
|
||||
if ( (swap = (l != k) )) {
|
||||
temp = col_k[l];
|
||||
col_k[l] = *diag_k;
|
||||
*diag_k = temp;
|
||||
}
|
||||
|
||||
/* Scale the elements below the diagonal in */
|
||||
/* column k by -1.0 / a(k,k). After the above swap, */
|
||||
/* a(k,k) holds the pivot element. This scaling */
|
||||
/* stores the pivot row multipliers -a(i,k)/a(k,k) */
|
||||
/* in a(i,k), i=k+1, ..., n-1. */
|
||||
|
||||
mult = -ONE / (*diag_k);
|
||||
for(i=k+1; i < n; i++)
|
||||
col_k[i] *= mult;
|
||||
|
||||
/* row_i = row_i - [a(i,k)/a(k,k)] row_k, i=k+1, ..., n-1 */
|
||||
/* row k is the pivot row after swapping with row l. */
|
||||
/* The computation is done one column at a time, */
|
||||
/* column j=k+1, ..., n-1. */
|
||||
|
||||
for (j=k+1; j < n; j++) {
|
||||
|
||||
col_j = a[j];
|
||||
a_kj = col_j[l];
|
||||
|
||||
/* Swap the elements a(k,j) and a(k,l) if l!=k. */
|
||||
|
||||
if (swap) {
|
||||
col_j[l] = col_j[k];
|
||||
col_j[k] = a_kj;
|
||||
}
|
||||
|
||||
/* a(i,j) = a(i,j) - [a(i,k)/a(k,k)]*a(k,j) */
|
||||
/* a_kj = a(k,j), col_k[i] = - a(i,k)/a(k,k) */
|
||||
|
||||
if (a_kj != ZERO) {
|
||||
for (i=k+1; i < n; i++)
|
||||
col_j[i] += a_kj * col_k[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set the last pivot row to be n-1 and check for a zero pivot */
|
||||
|
||||
*p = n-1;
|
||||
if (a[n-1][n-1] == ZERO) return(n);
|
||||
|
||||
/* return 0 to indicate success */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void gesl(real **a, integer n, integer *p, real *b)
|
||||
{
|
||||
integer k, l, i;
|
||||
real mult, *col_k;
|
||||
|
||||
/* Solve Ly = Pb, store solution y in b */
|
||||
|
||||
for (k=0; k < n-1; k++) {
|
||||
l = p[k];
|
||||
mult = b[l];
|
||||
if (l != k) {
|
||||
b[l] = b[k];
|
||||
b[k] = mult;
|
||||
}
|
||||
col_k = a[k];
|
||||
for (i=k+1; i < n; i++)
|
||||
b[i] += mult*col_k[i];
|
||||
}
|
||||
|
||||
/* Solve Ux = y, store solution x in b */
|
||||
|
||||
for (k=n-1; k >= 0; k--) {
|
||||
col_k = a[k];
|
||||
b[k] /= col_k[k];
|
||||
mult = -b[k];
|
||||
for (i=0; i < k; i++)
|
||||
b[i] += mult*col_k[i];
|
||||
}
|
||||
}
|
||||
|
||||
void denzero(real **a, integer n)
|
||||
{
|
||||
integer i, j;
|
||||
real *col_j;
|
||||
|
||||
for (j=0; j < n; j++) {
|
||||
col_j = a[j];
|
||||
for (i=0; i < n; i++)
|
||||
col_j[i] = ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
void dencopy(real **a, real **b, integer n)
|
||||
{
|
||||
integer i, j;
|
||||
real *a_col_j, *b_col_j;
|
||||
|
||||
for (j=0; j < n; j++) {
|
||||
a_col_j = a[j];
|
||||
b_col_j = b[j];
|
||||
for (i=0; i < n; i++)
|
||||
b_col_j[i] = a_col_j[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void denscale(real c, real **a, integer n)
|
||||
{
|
||||
integer i, j;
|
||||
real *col_j;
|
||||
|
||||
for (j=0; j < n; j++) {
|
||||
col_j = a[j];
|
||||
for (i=0; i < n; i++)
|
||||
col_j[i] *= c;
|
||||
}
|
||||
}
|
||||
|
||||
void denaddI(real **a, integer n)
|
||||
{
|
||||
integer i;
|
||||
|
||||
for (i=0; i < n; i++) a[i][i] += ONE;
|
||||
}
|
||||
|
||||
void denfreepiv(integer *p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
void denfree(real **a)
|
||||
{
|
||||
free(a[0]);
|
||||
free(a);
|
||||
}
|
||||
|
||||
void denprint(real **a, integer n)
|
||||
{
|
||||
integer i, j;
|
||||
|
||||
printf("\n");
|
||||
for (i=0; i < n; i++) {
|
||||
for (j=0; j < n; j++) {
|
||||
printf("%10g", a[j][i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
|
@ -1,258 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : iterativ.c *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 16 January 1998 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the implementation file for the iterativ.h header *
|
||||
* file. It contains the implementation of functions that may be *
|
||||
* useful for many different iterative solvers of A x = b. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
#include "iterativ.h"
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
#include "llnlmath.h"
|
||||
|
||||
|
||||
#define FACTOR RCONST(1000.0)
|
||||
#define ZERO RCONST(0.0)
|
||||
#define ONE RCONST(1.0)
|
||||
|
||||
|
||||
/************************* ModifiedGS ***********************************
|
||||
This implementation of ModifiedGS is a slight modification of a previous
|
||||
modified Gram-Schmidt routine (called mgs) written by Milo Dorr.
|
||||
*************************************************************************/
|
||||
|
||||
int ModifiedGS(N_Vector *v, real **h, int k, int p, real *new_vk_norm)
|
||||
{
|
||||
int i, k_minus_1, i0;
|
||||
real new_norm_2, new_product, vk_norm, temp;
|
||||
|
||||
vk_norm = RSqrt(N_VDotProd(v[k],v[k]));
|
||||
k_minus_1 = k - 1;
|
||||
i0 = MAX(k-p, 0);
|
||||
|
||||
/* Perform modified Gram-Schmidt */
|
||||
|
||||
for (i=i0; i < k; i++) {
|
||||
h[i][k_minus_1] = N_VDotProd(v[i], v[k]);
|
||||
N_VLinearSum(ONE, v[k], -h[i][k_minus_1], v[i], v[k]);
|
||||
}
|
||||
|
||||
/* Compute the norm of the new vector at v[k]. */
|
||||
|
||||
*new_vk_norm = RSqrt(N_VDotProd(v[k], v[k]));
|
||||
|
||||
/* If the norm of the new vector at v[k] is less than
|
||||
FACTOR (== 1000) times unit roundoff times the norm of the
|
||||
input vector v[k], then the vector will be reorthogonalized
|
||||
in order to ensure that nonorthogonality is not being masked
|
||||
by a very small vector length. */
|
||||
|
||||
temp = FACTOR * vk_norm;
|
||||
if ((temp + (*new_vk_norm)) != temp) return(0);
|
||||
|
||||
new_norm_2 = ZERO;
|
||||
|
||||
for (i=i0; i < k; i++) {
|
||||
new_product = N_VDotProd(v[i], v[k]);
|
||||
temp = FACTOR * h[i][k_minus_1];
|
||||
if ((temp + new_product) == temp) continue;
|
||||
h[i][k_minus_1] += new_product;
|
||||
N_VLinearSum(ONE, v[k],-new_product, v[i], v[k]);
|
||||
new_norm_2 += SQR(new_product);
|
||||
}
|
||||
|
||||
if (new_norm_2 != ZERO) {
|
||||
new_product = SQR(*new_vk_norm) - new_norm_2;
|
||||
*new_vk_norm = (new_product > ZERO) ? RSqrt(new_product) : ZERO;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/************************ ClassicalGS ********************************
|
||||
This implementation of ClassicalGS was contributed to by Homer Walker
|
||||
and Peter Brown.
|
||||
**********************************************************************/
|
||||
|
||||
int ClassicalGS(N_Vector *v, real **h, int k, int p, real *new_vk_norm,
|
||||
N_Vector temp, real *s)
|
||||
{
|
||||
int i, k_minus_1, i0;
|
||||
real vk_norm;
|
||||
|
||||
k_minus_1 = k - 1;
|
||||
|
||||
/* Perform Classical Gram-Schmidt */
|
||||
|
||||
vk_norm = RSqrt(N_VDotProd(v[k], v[k]));
|
||||
|
||||
i0 = MAX(k-p, 0);
|
||||
for (i=i0; i < k; i++) {
|
||||
h[i][k_minus_1] = N_VDotProd(v[i], v[k]);
|
||||
}
|
||||
|
||||
for (i=i0; i < k; i++) {
|
||||
N_VLinearSum(ONE, v[k], -h[i][k_minus_1], v[i], v[k]);
|
||||
}
|
||||
|
||||
/* Compute the norm of the new vector at v[k]. */
|
||||
|
||||
*new_vk_norm = RSqrt(N_VDotProd(v[k], v[k]));
|
||||
|
||||
/* Reorthogonalize if necessary */
|
||||
|
||||
if ((FACTOR * (*new_vk_norm)) < vk_norm) {
|
||||
|
||||
for (i=i0; i < k; i++) {
|
||||
s[i] = N_VDotProd(v[i], v[k]);
|
||||
}
|
||||
|
||||
if (i0 < k) {
|
||||
N_VScale(s[i0], v[i0], temp);
|
||||
h[i0][k_minus_1] += s[i0];
|
||||
}
|
||||
for (i=i0+1; i < k; i++) {
|
||||
N_VLinearSum(s[i], v[i], ONE, temp, temp);
|
||||
h[i][k_minus_1] += s[i];
|
||||
}
|
||||
N_VLinearSum(ONE, v[k], -ONE, temp, v[k]);
|
||||
|
||||
*new_vk_norm = RSqrt(N_VDotProd(v[k],v[k]));
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*************** QRfact **********************************************
|
||||
This implementation of QRfact is a slight modification of a previous
|
||||
routine (called qrfact) written by Milo Dorr.
|
||||
**********************************************************************/
|
||||
|
||||
int QRfact(int n, real **h, real *q, int job)
|
||||
{
|
||||
real c, s, temp1, temp2, temp3;
|
||||
int i, j, k, q_ptr, n_minus_1, code=0;
|
||||
|
||||
switch (job) {
|
||||
case 0:
|
||||
/* Compute a new factorization of H. */
|
||||
code = 0;
|
||||
for (k=0; k < n; k++) {
|
||||
|
||||
/* Multiply column k by the previous k-1 Givens rotations. */
|
||||
for (j=0; j < k-1; j++) {
|
||||
i = 2*j;
|
||||
temp1 = h[j][k];
|
||||
temp2 = h[j+1][k];
|
||||
c = q[i];
|
||||
s = q[i+1];
|
||||
h[j][k] = c*temp1 - s*temp2;
|
||||
h[j+1][k] = s*temp1 + c*temp2;
|
||||
}
|
||||
|
||||
/* Compute the Givens rotation components c and s */
|
||||
q_ptr = 2*k;
|
||||
temp1 = h[k][k];
|
||||
temp2 = h[k+1][k];
|
||||
if( temp2 == ZERO) {
|
||||
c = ONE;
|
||||
s = ZERO;
|
||||
} else if (ABS(temp2) >= ABS(temp1)) {
|
||||
temp3 = temp1/temp2;
|
||||
s = -ONE/RSqrt(ONE+SQR(temp3));
|
||||
c = -s*temp3;
|
||||
} else {
|
||||
temp3 = temp2/temp1;
|
||||
c = ONE/RSqrt(ONE+SQR(temp3));
|
||||
s = -c*temp3;
|
||||
}
|
||||
q[q_ptr] = c;
|
||||
q[q_ptr+1] = s;
|
||||
if( (h[k][k] = c*temp1 - s*temp2) == ZERO) code = k+1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Update the factored H to which a new column has been added. */
|
||||
n_minus_1 = n - 1;
|
||||
code = 0;
|
||||
|
||||
/* Multiply the new column by the previous n-1 Givens rotations. */
|
||||
for (k=0; k < n_minus_1; k++) {
|
||||
i = 2*k;
|
||||
temp1 = h[k][n_minus_1];
|
||||
temp2 = h[k+1][n_minus_1];
|
||||
c = q[i];
|
||||
s = q[i+1];
|
||||
h[k][n_minus_1] = c*temp1 - s*temp2;
|
||||
h[k+1][n_minus_1] = s*temp1 + c*temp2;
|
||||
}
|
||||
|
||||
/* Compute new Givens rotation and multiply it times the last two
|
||||
entries in the new column of H. Note that the second entry of
|
||||
this product will be 0, so it is not necessary to compute it. */
|
||||
temp1 = h[n_minus_1][n_minus_1];
|
||||
temp2 = h[n][n_minus_1];
|
||||
if (temp2 == ZERO) {
|
||||
c = ONE;
|
||||
s = ZERO;
|
||||
} else if (ABS(temp2) >= ABS(temp1)) {
|
||||
temp3 = temp1/temp2;
|
||||
s = -ONE/RSqrt(ONE+SQR(temp3));
|
||||
c = -s*temp3;
|
||||
} else {
|
||||
temp3 = temp2/temp1;
|
||||
c = ONE/RSqrt(ONE+SQR(temp3));
|
||||
s = -c*temp3;
|
||||
}
|
||||
q_ptr = 2*n_minus_1;
|
||||
q[q_ptr] = c;
|
||||
q[q_ptr+1] = s;
|
||||
if ((h[n_minus_1][n_minus_1] = c*temp1 - s*temp2) == ZERO)
|
||||
code = n;
|
||||
}
|
||||
|
||||
return (code);
|
||||
}
|
||||
|
||||
/*************** QRsol ************************************************
|
||||
This implementation of QRsol is a slight modification of a previous
|
||||
routine (called qrsol) written by Milo Dorr.
|
||||
**********************************************************************/
|
||||
|
||||
int QRsol(int n, real **h, real *q, real *b)
|
||||
{
|
||||
real c, s, temp1, temp2;
|
||||
int i, k, q_ptr, code=0;
|
||||
|
||||
/* Compute Q*b. */
|
||||
|
||||
for (k=0; k < n; k++) {
|
||||
q_ptr = 2*k;
|
||||
c = q[q_ptr];
|
||||
s = q[q_ptr+1];
|
||||
temp1 = b[k];
|
||||
temp2 = b[k+1];
|
||||
b[k] = c*temp1 - s*temp2;
|
||||
b[k+1] = s*temp1 + c*temp2;
|
||||
}
|
||||
|
||||
/* Solve R*x = Q*b. */
|
||||
|
||||
for (k=n-1; k >= 0; k--) {
|
||||
if (h[k][k] == ZERO) {
|
||||
code = k + 1;
|
||||
break;
|
||||
}
|
||||
b[k] /= h[k][k];
|
||||
for (i=0; i < k; i++) b[i] -= b[k]*h[i][k];
|
||||
}
|
||||
|
||||
return (code);
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/******************************************************************
|
||||
* *
|
||||
* File : llnlmath.c *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 1 September 1994 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the implementation file for a C math library. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "llnlmath.h"
|
||||
#include "llnltyps.h"
|
||||
|
||||
|
||||
#define ZERO RCONST(0.0)
|
||||
#define ONE RCONST(1.0)
|
||||
#define TWO RCONST(2.0)
|
||||
|
||||
|
||||
real UnitRoundoff(void)
|
||||
{
|
||||
real u;
|
||||
volatile real one_plus_u;
|
||||
|
||||
u = ONE;
|
||||
one_plus_u = ONE + u;
|
||||
while (one_plus_u != ONE) {
|
||||
u /= TWO;
|
||||
one_plus_u = ONE + u;
|
||||
}
|
||||
u *= TWO;
|
||||
|
||||
return(u);
|
||||
}
|
||||
|
||||
|
||||
real RPowerI(real base, int exponent)
|
||||
{
|
||||
int i, expt;
|
||||
real prod;
|
||||
|
||||
prod = ONE;
|
||||
expt = ABS(exponent);
|
||||
for(i=1; i <= expt; i++) prod *= base;
|
||||
if (exponent < 0) prod = ONE/prod;
|
||||
return(prod);
|
||||
}
|
||||
|
||||
|
||||
real RPowerR(real base, real exponent)
|
||||
{
|
||||
|
||||
if (base <= ZERO) return(ZERO);
|
||||
|
||||
return((real)pow((double)base,(double)exponent));
|
||||
}
|
||||
|
||||
|
||||
real RSqrt(real x)
|
||||
{
|
||||
if (x <= ZERO) return(ZERO);
|
||||
|
||||
return((real) sqrt((double) x));
|
||||
}
|
||||
|
|
@ -1,672 +0,0 @@
|
|||
/****************************************************************
|
||||
* *
|
||||
* File : nvector.c *
|
||||
* Programmers : Scott D. Cohen, Alan C. Hindmarsh, and *
|
||||
* : Allan G. Taylor, LLNL *
|
||||
* Version of : 17 December 1999 *
|
||||
*--------------------------------------------------------------*
|
||||
* *
|
||||
* This is the implementation file for a generic serial NVECTOR *
|
||||
* package. It contains the implementation of the N_Vector *
|
||||
* kernels listed in nvector.h. *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "nvector.h"
|
||||
#include "llnltyps.h"
|
||||
#include "llnlmath.h"
|
||||
|
||||
|
||||
#define ZERO RCONST(0.0)
|
||||
#define HALF RCONST(0.5)
|
||||
#define ONE RCONST(1.0)
|
||||
#define ONEPT5 RCONST(1.5)
|
||||
|
||||
|
||||
/* Private Helper Prototypes */
|
||||
|
||||
static void VCopy(N_Vector x, N_Vector z); /* z=x */
|
||||
static void VSum(N_Vector x, N_Vector y, N_Vector z); /* z=x+y */
|
||||
static void VDiff(N_Vector x, N_Vector y, N_Vector z); /* z=x-y */
|
||||
static void VNeg(N_Vector x, N_Vector z); /* z=-x */
|
||||
/* z=c(x+y) */
|
||||
static void VScaleSum(real c, N_Vector x, N_Vector y, N_Vector z);
|
||||
/* z=c(x-y) */
|
||||
static void VScaleDiff(real c, N_Vector x, N_Vector y, N_Vector z);
|
||||
static void VLin1(real a, N_Vector x, N_Vector y, N_Vector z); /* z=ax+y */
|
||||
static void VLin2(real a, N_Vector x, N_Vector y, N_Vector z); /* z=ax-y */
|
||||
static void Vaxpy(real a, N_Vector x, N_Vector y); /* y <- ax+y */
|
||||
static void VScaleBy(real a, N_Vector x); /* x <- ax */
|
||||
|
||||
/********************* Exported Functions ************************/
|
||||
|
||||
|
||||
N_Vector N_VNew(integer N, void *machEnv)
|
||||
{
|
||||
N_Vector v;
|
||||
|
||||
if (N <= 0) return(NULL);
|
||||
|
||||
v = (N_Vector) malloc(sizeof *v);
|
||||
if (v == NULL) return(NULL);
|
||||
|
||||
v->data = (real *) malloc(N * sizeof(real));
|
||||
if (v->data == NULL) {
|
||||
free(v);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
v->length = N;
|
||||
|
||||
return(v);
|
||||
}
|
||||
|
||||
|
||||
void N_VFree(N_Vector x)
|
||||
{
|
||||
free(x->data);
|
||||
free(x);
|
||||
}
|
||||
|
||||
|
||||
void N_VLinearSum(real a, N_Vector x, real b, N_Vector y, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real c, *xd, *yd, *zd;
|
||||
N_Vector v1, v2;
|
||||
boole test;
|
||||
|
||||
if ((b == ONE) && (z == y)) { /* BLAS usage: axpy y <- ax+y */
|
||||
Vaxpy(a,x,y);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((a == ONE) && (z == x)) { /* BLAS usage: axpy x <- by+x */
|
||||
Vaxpy(b,y,x);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Case: a == b == 1.0 */
|
||||
|
||||
if ((a == ONE) && (b == ONE)) {
|
||||
VSum(x, y, z);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Cases: (1) a == 1.0, b = -1.0, (2) a == -1.0, b == 1.0 */
|
||||
|
||||
if ((test = ((a == ONE) && (b == -ONE))) || ((a == -ONE) && (b == ONE))) {
|
||||
v1 = test ? y : x;
|
||||
v2 = test ? x : y;
|
||||
VDiff(v2, v1, z);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Cases: (1) a == 1.0, b == other or 0.0, (2) a == other or 0.0, b == 1.0 */
|
||||
/* if a or b is 0.0, then user should have called N_VScale */
|
||||
|
||||
if ((test = (a == ONE)) || (b == ONE)) {
|
||||
c = test ? b : a;
|
||||
v1 = test ? y : x;
|
||||
v2 = test ? x : y;
|
||||
VLin1(c, v1, v2, z);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Cases: (1) a == -1.0, b != 1.0, (2) a != 1.0, b == -1.0 */
|
||||
|
||||
if ((test = (a == -ONE)) || (b == -ONE)) {
|
||||
c = test ? b : a;
|
||||
v1 = test ? y : x;
|
||||
v2 = test ? x : y;
|
||||
VLin2(c, v1, v2, z);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Case: a == b */
|
||||
/* catches case both a and b are 0.0 - user should have called N_VConst */
|
||||
|
||||
if (a == b) {
|
||||
VScaleSum(a, x, y, z);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Case: a == -b */
|
||||
|
||||
if (a == -b) {
|
||||
VScaleDiff(a, x, y, z);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do all cases not handled above:
|
||||
(1) a == other, b == 0.0 - user should have called N_VScale
|
||||
(2) a == 0.0, b == other - user should have called N_VScale
|
||||
(3) a,b == other, a !=b, a != -b */
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
yd = y->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*zd++ = a * (*xd++) + b * (*yd++);
|
||||
}
|
||||
|
||||
|
||||
void N_VConst(real c, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *zd;
|
||||
|
||||
N = z->length;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*zd++ = c;
|
||||
}
|
||||
|
||||
|
||||
void N_VProd(N_Vector x, N_Vector y, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *yd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
yd = y->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*zd++ = (*xd++) * (*yd++);
|
||||
}
|
||||
|
||||
|
||||
void N_VDiv(N_Vector x, N_Vector y, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *yd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
yd = y->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*zd++ = (*xd++) / (*yd++);
|
||||
}
|
||||
|
||||
|
||||
void N_VScale(real c, N_Vector x, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *zd;
|
||||
|
||||
if (z == x) { /* BLAS usage: scale x <- cx */
|
||||
VScaleBy(c, x);
|
||||
return;
|
||||
}
|
||||
|
||||
if (c == ONE) {
|
||||
VCopy(x, z);
|
||||
} else if (c == -ONE) {
|
||||
VNeg(x, z);
|
||||
} else {
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
zd = z->data;
|
||||
for (i=0; i < N; i++) *zd++ = c * (*xd++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void N_VAbs(N_Vector x, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++, xd++, zd++)
|
||||
*zd = ABS(*xd);
|
||||
}
|
||||
|
||||
|
||||
void N_VInv(N_Vector x, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*zd++ = ONE / (*xd++);
|
||||
}
|
||||
|
||||
|
||||
void N_VAddConst(N_Vector x, real b, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++) *zd++ = (*xd++) + b;
|
||||
}
|
||||
|
||||
|
||||
real N_VDotProd(N_Vector x, N_Vector y)
|
||||
{
|
||||
integer i, N;
|
||||
real sum = ZERO, *xd, *yd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
yd = y->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
sum += (*xd++) * (*yd++);
|
||||
|
||||
return(sum);
|
||||
}
|
||||
|
||||
|
||||
real N_VMaxNorm(N_Vector x)
|
||||
{
|
||||
integer i, N;
|
||||
real max = ZERO, *xd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
|
||||
for (i=0; i < N; i++, xd++) {
|
||||
if (ABS(*xd) > max) max = ABS(*xd);
|
||||
}
|
||||
|
||||
return(max);
|
||||
}
|
||||
|
||||
|
||||
real N_VWrmsNorm(N_Vector x, N_Vector w)
|
||||
{
|
||||
integer i, N;
|
||||
real sum = ZERO, prodi, *xd, *wd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
wd = w->data;
|
||||
|
||||
for (i=0; i < N; i++) {
|
||||
prodi = (*xd++) * (*wd++);
|
||||
sum += prodi * prodi;
|
||||
}
|
||||
|
||||
return(RSqrt(sum / N));
|
||||
}
|
||||
|
||||
|
||||
|
||||
real N_VMin(N_Vector x)
|
||||
{
|
||||
integer i, N;
|
||||
real min, *xd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
min = xd[0];
|
||||
|
||||
for (i=1; i < N; i++, xd++) {
|
||||
if ((*xd) < min) min = *xd;
|
||||
}
|
||||
|
||||
return(min);
|
||||
}
|
||||
|
||||
|
||||
real N_VWL2Norm(N_Vector x, N_Vector w)
|
||||
{
|
||||
integer i, N;
|
||||
real sum = ZERO, prodi, *xd, *wd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
wd = w->data;
|
||||
|
||||
for (i=0; i < N; i++) {
|
||||
prodi = (*xd++) * (*wd++);
|
||||
sum += prodi * prodi;
|
||||
}
|
||||
|
||||
return(RSqrt(sum));
|
||||
}
|
||||
|
||||
|
||||
real N_VL1Norm(N_Vector x)
|
||||
{
|
||||
integer i, N;
|
||||
real sum = ZERO, *xd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
|
||||
for (i=0; i<N; i++)
|
||||
sum += ABS(xd[i]);
|
||||
|
||||
return(sum);
|
||||
}
|
||||
|
||||
|
||||
void N_VOneMask(N_Vector x)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
|
||||
for (i=0; i<N; i++,xd++) {
|
||||
if (*xd != ZERO) *xd = ONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void N_VCompare(real c, N_Vector x, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++, xd++, zd++) {
|
||||
*zd = (ABS(*xd) >= c) ? ONE : ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boole N_VInvTest(N_Vector x, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++) {
|
||||
if (*xd == ZERO) return(FALSE);
|
||||
*zd++ = ONE / (*xd++);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
boole N_VConstrProdPos(N_Vector c, N_Vector x)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *cd;
|
||||
boole test;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
cd = c->data;
|
||||
test = TRUE;
|
||||
|
||||
for (i=0; i < N; i++, xd++,cd++) {
|
||||
if (*cd != ZERO) {
|
||||
if ((*xd)*(*cd) <= ZERO) {
|
||||
test = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(test);
|
||||
}
|
||||
|
||||
boole N_VConstrMask(N_Vector c, N_Vector x, N_Vector m)
|
||||
{
|
||||
integer i, N;
|
||||
boole test;
|
||||
real *cd, *xd, *md;
|
||||
|
||||
N = x->length;
|
||||
cd = c->data;
|
||||
xd = x->data;
|
||||
md = m->data;
|
||||
|
||||
test = TRUE;
|
||||
|
||||
for (i=0; i<N; i++, cd++, xd++, md++) {
|
||||
if ( *cd == ZERO) *md = ZERO;
|
||||
else {
|
||||
if ( *cd > ONEPT5 || (*cd) < -ONEPT5) {
|
||||
if ( (*xd)*(*cd) <= ZERO) {
|
||||
test = FALSE;
|
||||
*md = ONE;
|
||||
}
|
||||
else {
|
||||
*md = ZERO;
|
||||
}
|
||||
} else if ( (*cd) > HALF || (*cd) < -HALF) {
|
||||
if ( (*xd)*(*cd) < ZERO ) {
|
||||
test = FALSE;
|
||||
*md = ONE;
|
||||
} else {
|
||||
*md = ZERO;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(test);
|
||||
}
|
||||
|
||||
|
||||
real N_VMinQuotient(N_Vector num, N_Vector denom)
|
||||
{
|
||||
boole notEvenOnce;
|
||||
integer i, N;
|
||||
real *nd, *dd, min;
|
||||
|
||||
N = num->length;
|
||||
nd = num->data;
|
||||
dd = denom->data;
|
||||
notEvenOnce = TRUE;
|
||||
|
||||
for (i=0; i<N; i++, nd++, dd++) {
|
||||
if (*dd == ZERO) continue;
|
||||
else {
|
||||
if (notEvenOnce) {
|
||||
min = *nd / *dd ;
|
||||
notEvenOnce = FALSE;
|
||||
}
|
||||
else
|
||||
min = MIN(min, (*nd)/(*dd));
|
||||
}
|
||||
}
|
||||
if (notEvenOnce) min = 1.e99;
|
||||
|
||||
return(min);
|
||||
}
|
||||
|
||||
|
||||
void N_VPrint(N_Vector x)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
|
||||
for (i=0; i < N; i++) printf("%11.8g\n", *xd++);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
/***************** Private Helper Functions **********************/
|
||||
|
||||
|
||||
static void VCopy(N_Vector x, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*zd++ = *xd++;
|
||||
}
|
||||
|
||||
|
||||
static void VSum(N_Vector x, N_Vector y, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *yd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
yd = y->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*zd++ = (*xd++) + (*yd++);
|
||||
}
|
||||
|
||||
|
||||
static void VDiff(N_Vector x, N_Vector y, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *yd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
yd = y->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*zd++ = (*xd++) - (*yd++);
|
||||
}
|
||||
|
||||
|
||||
static void VNeg(N_Vector x, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*zd++ = -(*xd++);
|
||||
}
|
||||
|
||||
|
||||
static void VScaleSum(real c, N_Vector x, N_Vector y, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *yd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
yd = y->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*zd++ = c * ((*xd++) + (*yd++));
|
||||
}
|
||||
|
||||
|
||||
static void VScaleDiff(real c, N_Vector x, N_Vector y, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *yd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
yd = y->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*zd++ = c * ((*xd++) - (*yd++));
|
||||
}
|
||||
|
||||
|
||||
static void VLin1(real a, N_Vector x, N_Vector y, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *yd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
yd = y->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*zd++ = a * (*xd++) + (*yd++);
|
||||
}
|
||||
|
||||
|
||||
static void VLin2(real a, N_Vector x, N_Vector y, N_Vector z)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *yd, *zd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
yd = y->data;
|
||||
zd = z->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*zd++ = a * (*xd++) - (*yd++);
|
||||
}
|
||||
|
||||
static void Vaxpy(real a, N_Vector x, N_Vector y)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd, *yd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
yd = y->data;
|
||||
|
||||
if (a == ONE) {
|
||||
for (i=0; i < N; i++)
|
||||
*yd++ += (*xd++);
|
||||
return;
|
||||
}
|
||||
|
||||
if (a == -ONE) {
|
||||
for (i=0; i < N; i++)
|
||||
*yd++ -= (*xd++);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*yd++ += a * (*xd++);
|
||||
}
|
||||
|
||||
static void VScaleBy(real a, N_Vector x)
|
||||
{
|
||||
integer i, N;
|
||||
real *xd;
|
||||
|
||||
N = x->length;
|
||||
xd = x->data;
|
||||
|
||||
for (i=0; i < N; i++)
|
||||
*xd++ *= a;
|
||||
}
|
||||
|
|
@ -1,429 +0,0 @@
|
|||
/******************************************************************
|
||||
* File : spgmr.c *
|
||||
* Programmers : Scott D. Cohen and Alan C. Hindmarsh @ LLNL *
|
||||
* Version of : 17 December 1999 *
|
||||
*----------------------------------------------------------------*
|
||||
* This is the implementation file for the scaled preconditioned *
|
||||
* GMRES (SPGMR) iterative linear solver. *
|
||||
* *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "iterativ.h"
|
||||
#include "spgmr.h"
|
||||
#include "llnltyps.h"
|
||||
#include "nvector.h"
|
||||
#include "llnlmath.h"
|
||||
|
||||
|
||||
#define ZERO RCONST(0.0)
|
||||
#define ONE RCONST(1.0)
|
||||
|
||||
|
||||
/*************** Private Helper Function Prototype *******************/
|
||||
|
||||
static void FreeVectorArray(N_Vector *A, int indMax);
|
||||
|
||||
|
||||
/* Implementation of SPGMR algorithm */
|
||||
|
||||
|
||||
/*************** SpgmrMalloc *****************************************/
|
||||
|
||||
SpgmrMem SpgmrMalloc(integer N, int l_max, void *machEnv)
|
||||
{
|
||||
SpgmrMem mem;
|
||||
N_Vector *V, xcor, vtemp;
|
||||
real **Hes, *givens, *yg;
|
||||
int k, i;
|
||||
|
||||
/* Check the input parameters. */
|
||||
|
||||
if ((N <= 0) || (l_max <= 0)) return(NULL);
|
||||
|
||||
/* Get memory for the Krylov basis vectors V[0], ..., V[l_max]. */
|
||||
|
||||
V = (N_Vector *) malloc((l_max+1)*sizeof(N_Vector));
|
||||
if (V == NULL) return(NULL);
|
||||
|
||||
for (k = 0; k <= l_max; k++) {
|
||||
V[k] = N_VNew(N, machEnv);
|
||||
if (V[k] == NULL) {
|
||||
FreeVectorArray(V, k-1);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get memory for the Hessenberg matrix Hes. */
|
||||
|
||||
Hes = (real **) malloc((l_max+1)*sizeof(real *));
|
||||
if (Hes == NULL) {
|
||||
FreeVectorArray(V, l_max);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
for (k = 0; k <= l_max; k++) {
|
||||
Hes[k] = (real *) malloc(l_max*sizeof(real));
|
||||
if (Hes[k] == NULL) {
|
||||
for (i = 0; i < k; i++) free(Hes[i]);
|
||||
FreeVectorArray(V, l_max);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get memory for Givens rotation components. */
|
||||
|
||||
givens = (real *) malloc(2*l_max*sizeof(real));
|
||||
if (givens == NULL) {
|
||||
for (i = 0; i <= l_max; i++) free(Hes[i]);
|
||||
FreeVectorArray(V, l_max);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Get memory to hold the correction to z_tilde. */
|
||||
|
||||
xcor = N_VNew(N, machEnv);
|
||||
if (xcor == NULL) {
|
||||
free(givens);
|
||||
for (i = 0; i <= l_max; i++) free(Hes[i]);
|
||||
FreeVectorArray(V, l_max);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Get memory to hold SPGMR y and g vectors. */
|
||||
|
||||
yg = (real *) malloc((l_max+1)*sizeof(real));
|
||||
if (yg == NULL) {
|
||||
N_VFree(xcor);
|
||||
free(givens);
|
||||
for (i = 0; i <= l_max; i++) free(Hes[i]);
|
||||
FreeVectorArray(V, l_max);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Get an array to hold a temporary vector. */
|
||||
|
||||
vtemp = N_VNew(N, machEnv);
|
||||
if (vtemp == NULL) {
|
||||
free(yg);
|
||||
N_VFree(xcor);
|
||||
free(givens);
|
||||
for (i = 0; i <= l_max; i++) free(Hes[i]);
|
||||
FreeVectorArray(V, l_max);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Get memory for an SpgmrMemRec containing SPGMR matrices and vectors. */
|
||||
|
||||
mem = (SpgmrMem) malloc(sizeof(SpgmrMemRec));
|
||||
if (mem == NULL) {
|
||||
N_VFree(vtemp);
|
||||
free(yg);
|
||||
N_VFree(xcor);
|
||||
free(givens);
|
||||
for (i = 0; i <= l_max; i++) free(Hes[i]);
|
||||
FreeVectorArray(V, l_max);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Set the fields of mem. */
|
||||
|
||||
mem->N = N;
|
||||
mem->l_max = l_max;
|
||||
mem->V = V;
|
||||
mem->Hes = Hes;
|
||||
mem->givens = givens;
|
||||
mem->xcor = xcor;
|
||||
mem->yg = yg;
|
||||
mem->vtemp = vtemp;
|
||||
|
||||
/* Return the pointer to SPGMR memory. */
|
||||
|
||||
return(mem);
|
||||
}
|
||||
|
||||
|
||||
/*************** SpgmrSolve ******************************************/
|
||||
|
||||
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)
|
||||
{
|
||||
N_Vector *V, xcor, vtemp;
|
||||
real **Hes, *givens, *yg;
|
||||
real beta, rotation_product, r_norm, s_product, rho;
|
||||
boole preOnLeft, preOnRight, scale2, scale1, converged;
|
||||
int i, j, k, l, l_plus_1, l_max, krydim, ier, ntries;
|
||||
|
||||
if (mem == NULL) return(SPGMR_MEM_NULL);
|
||||
|
||||
/* Make local copies of mem variables. */
|
||||
l_max = mem->l_max;
|
||||
V = mem->V;
|
||||
Hes = mem->Hes;
|
||||
givens = mem->givens;
|
||||
xcor = mem->xcor;
|
||||
yg = mem->yg;
|
||||
vtemp = mem->vtemp;
|
||||
|
||||
*nli = *nps = 0; /* Initialize counters */
|
||||
converged = FALSE; /* Initialize converged flag */
|
||||
|
||||
if (max_restarts < 0) max_restarts = 0;
|
||||
|
||||
if ((pretype != LEFT) && (pretype != RIGHT) && (pretype != BOTH))
|
||||
pretype = NONE;
|
||||
|
||||
preOnLeft = ((pretype == LEFT) || (pretype == BOTH));
|
||||
preOnRight = ((pretype == RIGHT) || (pretype == BOTH));
|
||||
scale1 = (s1 != NULL);
|
||||
scale2 = (s2 != NULL);
|
||||
|
||||
/* Set vtemp and V[0] to initial (unscaled) residual r_0 = b - A*x_0. */
|
||||
|
||||
if (N_VDotProd(x, x) == ZERO) {
|
||||
N_VScale(ONE, b, vtemp);
|
||||
} else {
|
||||
if (atimes(A_data, x, vtemp) != 0)
|
||||
return(SPGMR_ATIMES_FAIL);
|
||||
N_VLinearSum(ONE, b, -ONE, vtemp, vtemp);
|
||||
}
|
||||
N_VScale(ONE, vtemp, V[0]);
|
||||
|
||||
/* Apply left preconditioner and left scaling to V[0] = r_0. */
|
||||
|
||||
if (preOnLeft) {
|
||||
ier = psolve(P_data, V[0], vtemp, LEFT);
|
||||
(*nps)++;
|
||||
if (ier != 0)
|
||||
return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
|
||||
} else {
|
||||
N_VScale(ONE, V[0], vtemp);
|
||||
}
|
||||
|
||||
if (scale1) {
|
||||
N_VProd(s1, vtemp, V[0]);
|
||||
} else {
|
||||
N_VScale(ONE, vtemp, V[0]);
|
||||
}
|
||||
|
||||
/* Set r_norm = beta to L2 norm of V[0] = s1 P1_inv r_0, and
|
||||
return if small. */
|
||||
|
||||
*res_norm = r_norm = beta = RSqrt(N_VDotProd(V[0], V[0]));
|
||||
if (r_norm <= delta)
|
||||
return(SPGMR_SUCCESS);
|
||||
|
||||
/* Set xcor = 0. */
|
||||
|
||||
N_VConst(ZERO, xcor);
|
||||
|
||||
|
||||
/* Begin outer iterations: up to (max_restarts + 1) attempts. */
|
||||
|
||||
for (ntries = 0; ntries <= max_restarts; ntries++) {
|
||||
|
||||
/* Initialize the Hessenberg matrix Hes and Givens rotation
|
||||
product. Normalize the initial vector V[0]. */
|
||||
|
||||
for (i = 0; i <= l_max; i++)
|
||||
for (j = 0; j < l_max; j++)
|
||||
Hes[i][j] = ZERO;
|
||||
|
||||
rotation_product = ONE;
|
||||
|
||||
N_VScale(ONE/r_norm, V[0], V[0]);
|
||||
|
||||
/* Inner loop: generate Krylov sequence and Arnoldi basis. */
|
||||
|
||||
for (l = 0; l < l_max; l++) {
|
||||
|
||||
(*nli)++;
|
||||
|
||||
krydim = l_plus_1 = l + 1;
|
||||
|
||||
/* Generate A-tilde V[l], where A-tilde = s1 P1_inv A P2_inv s2_inv. */
|
||||
|
||||
/* Apply right scaling: vtemp = s2_inv V[l]. */
|
||||
if (scale2) N_VDiv(V[l], s2, vtemp);
|
||||
else N_VScale(ONE, V[l], vtemp);
|
||||
|
||||
/* Apply right preconditioner: vtemp = P2_inv s2_inv V[l]. */
|
||||
if (preOnRight) {
|
||||
N_VScale(ONE, vtemp, V[l_plus_1]);
|
||||
ier = psolve(P_data, V[l_plus_1], vtemp, RIGHT);
|
||||
(*nps)++;
|
||||
if (ier != 0)
|
||||
return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
|
||||
}
|
||||
|
||||
/* Apply A: V[l+1] = A P2_inv s2_inv V[l]. */
|
||||
if (atimes(A_data, vtemp, V[l_plus_1] ) != 0)
|
||||
return(SPGMR_ATIMES_FAIL);
|
||||
|
||||
/* Apply left preconditioning: vtemp = P1_inv A P2_inv s2_inv V[l]. */
|
||||
if (preOnLeft) {
|
||||
ier = psolve(P_data, V[l_plus_1], vtemp, LEFT);
|
||||
(*nps)++;
|
||||
if (ier != 0)
|
||||
return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
|
||||
} else {
|
||||
N_VScale(ONE, V[l_plus_1], vtemp);
|
||||
}
|
||||
|
||||
/* Apply left scaling: V[l+1] = s1 P1_inv A P2_inv s2_inv V[l]. */
|
||||
if (scale1) {
|
||||
N_VProd(s1, vtemp, V[l_plus_1]);
|
||||
} else {
|
||||
N_VScale(ONE, vtemp, V[l_plus_1]);
|
||||
}
|
||||
|
||||
/* Orthogonalize V[l+1] against previous V[i]: V[l+1] = w_tilde. */
|
||||
|
||||
if (gstype == CLASSICAL_GS) {
|
||||
if (ClassicalGS(V, Hes, l_plus_1, l_max, &(Hes[l_plus_1][l]),
|
||||
vtemp, yg) != 0)
|
||||
return(SPGMR_GS_FAIL);
|
||||
} else {
|
||||
if (ModifiedGS(V, Hes, l_plus_1, l_max, &(Hes[l_plus_1][l])) != 0)
|
||||
return(SPGMR_GS_FAIL);
|
||||
}
|
||||
|
||||
/* Update the QR factorization of Hes. */
|
||||
|
||||
if(QRfact(krydim, Hes, givens, l) != 0 )
|
||||
return(SPGMR_QRFACT_FAIL);
|
||||
|
||||
/* Update residual norm estimate; break if convergence test passes. */
|
||||
|
||||
rotation_product *= givens[2*l+1];
|
||||
*res_norm = rho = ABS(rotation_product*r_norm);
|
||||
|
||||
if (rho <= delta) { converged = TRUE; break; }
|
||||
|
||||
/* Normalize V[l+1] with norm value from the Gram-Schmidt routine. */
|
||||
N_VScale(ONE/Hes[l_plus_1][l], V[l_plus_1], V[l_plus_1]);
|
||||
}
|
||||
|
||||
/* Inner loop is done. Compute the new correction vector xcor. */
|
||||
|
||||
/* Construct g, then solve for y. */
|
||||
yg[0] = r_norm;
|
||||
for (i = 1; i <= krydim; i++) yg[i]=ZERO;
|
||||
if (QRsol(krydim, Hes, givens, yg) != 0)
|
||||
return(SPGMR_QRSOL_FAIL);
|
||||
|
||||
/* Add correction vector V_l y to xcor. */
|
||||
for (k = 0; k < krydim; k++)
|
||||
N_VLinearSum(yg[k], V[k], ONE, xcor, xcor);
|
||||
|
||||
/* If converged, construct the final solution vector x and return. */
|
||||
if (converged) {
|
||||
|
||||
/* Apply right scaling and right precond.: vtemp = P2_inv s2_inv xcor. */
|
||||
|
||||
if (scale2) N_VDiv(xcor, s2, xcor);
|
||||
if (preOnRight) {
|
||||
ier = psolve(P_data, xcor, vtemp, RIGHT);
|
||||
(*nps)++;
|
||||
if (ier != 0)
|
||||
return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
|
||||
} else {
|
||||
N_VScale(ONE, xcor, vtemp);
|
||||
}
|
||||
|
||||
/* Add vtemp to initial x to get final solution x, and return */
|
||||
N_VLinearSum(ONE, x, ONE, vtemp, x);
|
||||
|
||||
return(SPGMR_SUCCESS);
|
||||
}
|
||||
|
||||
/* Not yet converged; if allowed, prepare for restart. */
|
||||
|
||||
if (ntries == max_restarts) break;
|
||||
|
||||
/* Construct last column of Q in yg. */
|
||||
s_product = ONE;
|
||||
for (i = krydim; i > 0; i--) {
|
||||
yg[i] = s_product*givens[2*i-2];
|
||||
s_product *= givens[2*i-1];
|
||||
}
|
||||
yg[0] = s_product;
|
||||
|
||||
/* Scale r_norm and yg. */
|
||||
r_norm *= s_product;
|
||||
for (i = 0; i <= krydim; i++)
|
||||
yg[i] *= r_norm;
|
||||
r_norm = ABS(r_norm);
|
||||
|
||||
/* Multiply yg by V_(krydim+1) to get last residual vector; restart. */
|
||||
N_VScale(yg[0], V[0], V[0]);
|
||||
for (k = 1; k <= krydim; k++)
|
||||
N_VLinearSum(yg[k], V[k], ONE, V[0], V[0]);
|
||||
|
||||
}
|
||||
|
||||
/* Failed to converge, even after allowed restarts.
|
||||
If the residual norm was reduced below its initial value, compute
|
||||
and return x anyway. Otherwise return failure flag. */
|
||||
|
||||
if (rho < beta) {
|
||||
|
||||
/* Apply right scaling and right precond.: vtemp = P2_inv s2_inv xcor. */
|
||||
|
||||
if (scale2) N_VDiv(xcor, s2, xcor);
|
||||
if (preOnRight) {
|
||||
ier = psolve(P_data, xcor, vtemp, RIGHT);
|
||||
(*nps)++;
|
||||
if (ier != 0)
|
||||
return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
|
||||
} else {
|
||||
N_VScale(ONE, xcor, vtemp);
|
||||
}
|
||||
|
||||
/* Add vtemp to initial x to get final solution x, and return. */
|
||||
N_VLinearSum(ONE, x, ONE, vtemp, x);
|
||||
|
||||
return(SPGMR_RES_REDUCED);
|
||||
}
|
||||
|
||||
return(SPGMR_CONV_FAIL);
|
||||
}
|
||||
|
||||
/*************** SpgmrFree *******************************************/
|
||||
|
||||
void SpgmrFree(SpgmrMem mem)
|
||||
{
|
||||
int i, l_max;
|
||||
real **Hes;
|
||||
|
||||
if (mem == NULL) return;
|
||||
|
||||
l_max = mem->l_max;
|
||||
Hes = mem->Hes;
|
||||
|
||||
FreeVectorArray(mem->V, l_max);
|
||||
for (i = 0; i <= l_max; i++) free(Hes[i]);
|
||||
free(Hes);
|
||||
free(mem->givens);
|
||||
N_VFree(mem->xcor);
|
||||
free(mem->yg);
|
||||
N_VFree(mem->vtemp);
|
||||
|
||||
free(mem);
|
||||
}
|
||||
|
||||
|
||||
/*************** Private Helper Function: FreeVectorArray ************/
|
||||
|
||||
static void FreeVectorArray(N_Vector *A, int indMax)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; j <= indMax; j++) N_VFree(A[j]);
|
||||
|
||||
free(A);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue