NEURON
arnoldi.c
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 /**************************************************************************
4 **
5 ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
6 **
7 ** Meschach Library
8 **
9 ** This Meschach Library is provided "as is" without any express
10 ** or implied warranty of any kind with respect to this software.
11 ** In particular the authors shall not be liable for any direct,
12 ** indirect, special, incidental or consequential damages arising
13 ** in any way from use of the software.
14 **
15 ** Everyone is granted permission to copy, modify and redistribute this
16 ** Meschach Library, provided:
17 ** 1. All copies contain this copyright notice.
18 ** 2. All modified copies shall carry a notice stating who
19 ** made the last modification and the date of such modification.
20 ** 3. No charge is made for this software or works derived from it.
21 ** This clause shall not be construed as constraining other software
22 ** distributed on the same medium as this software, nor is a
23 ** distribution fee considered a charge.
24 **
25 ***************************************************************************/
26 
27 /*
28  Arnoldi method for finding eigenvalues of large non-symmetric
29  matrices
30 */
31 #include <stdio.h>
32 #include <math.h>
33 #include "matrix.h"
34 #include "matrix2.h"
35 #include "sparse.h"
36 
37 static char rcsid[] = "arnoldi.c,v 1.1 1997/12/04 17:55:13 hines Exp";
38 
39 /* arnoldi -- an implementation of the Arnoldi method */
40 MAT *arnoldi(A,A_param,x0,m,h_rem,Q,H)
41 VEC *(*A)();
42 void *A_param;
43 VEC *x0;
44 int m;
45 Real *h_rem;
46 MAT *Q, *H;
47 {
48  static VEC *v=VNULL, *u=VNULL, *r=VNULL, *s=VNULL, *tmp=VNULL;
49  int i;
50  Real h_val;
51 
52  if ( ! A || ! Q || ! x0 )
53  error(E_NULL,"arnoldi");
54  if ( m <= 0 )
55  error(E_BOUNDS,"arnoldi");
56  if ( Q->n != x0->dim || Q->m != m )
57  error(E_SIZES,"arnoldi");
58 
59  m_zero(Q);
60  H = m_resize(H,m,m);
61  m_zero(H);
62  u = v_resize(u,x0->dim);
63  v = v_resize(v,x0->dim);
64  r = v_resize(r,m);
65  s = v_resize(s,m);
66  tmp = v_resize(tmp,x0->dim);
72  sv_mlt(1.0/v_norm2(x0),x0,v);
73  for ( i = 0; i < m; i++ )
74  {
75  set_row(Q,i,v);
76  u = (*A)(A_param,v,u);
77  r = mv_mlt(Q,u,r);
78  tmp = vm_mlt(Q,r,tmp);
79  v_sub(u,tmp,u);
80  h_val = v_norm2(u);
81  /* if u == 0 then we have an exact subspace */
82  if ( h_val == 0.0 )
83  {
84  *h_rem = h_val;
85  return H;
86  }
87  /* iterative refinement -- ensures near orthogonality */
88  do {
89  s = mv_mlt(Q,u,s);
90  tmp = vm_mlt(Q,s,tmp);
91  v_sub(u,tmp,u);
92  v_add(r,s,r);
93  } while ( v_norm2(s) > 0.1*(h_val = v_norm2(u)) );
94  /* now that u is nearly orthogonal to Q, update H */
95  set_col(H,i,r);
96  if ( i == m-1 )
97  {
98  *h_rem = h_val;
99  continue;
100  }
101  /* H->me[i+1][i] = h_val; */
102  m_set_val(H,i+1,i,h_val);
103  sv_mlt(1.0/h_val,u,v);
104  }
105 
106  return H;
107 }
108 
109 /* sp_arnoldi -- uses arnoldi() with an explicit representation of A */
110 MAT *sp_arnoldi(A,x0,m,h_rem,Q,H)
111 SPMAT *A;
112 VEC *x0;
113 int m;
114 Real *h_rem;
115 MAT *Q, *H;
116 { return arnoldi(sp_mv_mlt,A,x0,m,h_rem,Q,H); }
117 
118 /* gmres -- generalised minimum residual algorithm of Saad & Schultz
119  SIAM J. Sci. Stat. Comp. v.7, pp.856--869 (1986)
120  -- y is overwritten with the solution */
121 VEC *gmres(A,A_param,m,Q,R,b,tol,x)
122 VEC *(*A)();
123 void *A_param;
124 VEC *b, *x;
125 int m;
126 MAT *Q, *R;
127 double tol;
128 {
129  static VEC *v=VNULL, *u=VNULL, *r=VNULL, *tmp=VNULL, *rhs=VNULL;
130  static VEC *diag=VNULL, *beta=VNULL;
131  int i;
132  Real h_val, norm_b;
133 
134  if ( ! A || ! Q || ! b || ! R )
135  error(E_NULL,"gmres");
136  if ( m <= 0 )
137  error(E_BOUNDS,"gmres");
138  if ( Q->n != b->dim || Q->m != m )
139  error(E_SIZES,"gmres");
140 
141  x = v_copy(b,x);
142  m_zero(Q);
143  R = m_resize(R,m+1,m);
144  m_zero(R);
145  u = v_resize(u,x->dim);
146  v = v_resize(v,x->dim);
147  tmp = v_resize(tmp,x->dim);
148  rhs = v_resize(rhs,m+1);
152  MEM_STAT_REG(tmp,TYPE_VEC);
154  norm_b = v_norm2(x);
155  if ( norm_b == 0.0 )
156  error(E_RANGE,"gmres");
157  sv_mlt(1.0/norm_b,x,v);
158 
159  for ( i = 0; i < m; i++ )
160  {
161  set_row(Q,i,v);
162  tracecatch(u = (*A)(A_param,v,u),"gmres");
163  r = mv_mlt(Q,u,r);
164  tmp = vm_mlt(Q,r,tmp);
165  v_sub(u,tmp,u);
166  h_val = v_norm2(u);
167  set_col(R,i,r);
168  R->me[i+1][i] = h_val;
169  sv_mlt(1.0/h_val,u,v);
170  }
171 
172  /* use i x i submatrix of R */
173  R = m_resize(R,i+1,i);
174  rhs = v_resize(rhs,i+1);
175  v_zero(rhs);
176  rhs->ve[0] = norm_b;
177  tmp = v_resize(tmp,i);
178  diag = v_resize(diag,i+1);
179  beta = v_resize(beta,i+1);
180  MEM_STAT_REG(beta,TYPE_VEC);
182  QRfactor(R,diag /* ,beta */);
183  tmp = QRsolve(R,diag, /* beta, */ rhs,tmp);
184  v_resize(tmp,m);
185  vm_mlt(Q,tmp,x);
186 
187  return x;
188 }
VEC * gmres(VEC *(*A)(), void *A_param, int m, MAT *Q, MAT *R, VEC *b, double tol, VEC *x)
Definition: arnoldi.c:121
MAT * arnoldi(VEC *(*A)(), void *A_param, VEC *x0, int m, Real *h_rem, MAT *Q, MAT *H)
Definition: arnoldi.c:40
MAT * sp_arnoldi(SPMAT *A, VEC *x0, int m, Real *h_rem, MAT *Q, MAT *H)
Definition: arnoldi.c:110
static char rcsid[]
Definition: arnoldi.c:37
#define error(err_num, fn_name)
Definition: err.h:73
#define tracecatch(ok_part, function)
Definition: err.h:166
#define E_RANGE
Definition: err.h:104
#define E_NULL
Definition: err.h:102
#define E_BOUNDS
Definition: err.h:96
#define E_SIZES
Definition: err.h:95
#define diag(s)
Definition: fmenu.cpp:192
VEC * v_zero(VEC *x)
Definition: init.c:40
static Object ** v_add(void *v1)
Definition: ivocvect.cpp:2317
static Object ** v_sub(void *v1)
Definition: ivocvect.cpp:2334
static Object ** v_resize(void *v)
Definition: ivocvect.cpp:1383
#define rhs
Definition: lineq.h:6
#define Real
Definition: machine.h:189
VEC * vm_mlt(MAT *A, VEC *b, VEC *out)
Definition: matop.c:263
VEC * mv_mlt(MAT *A, VEC *b, VEC *out)
Definition: matop.c:205
MAT * QRfactor(MAT *A, VEC *diag)
VEC * QRsolve(MAT *A, VEC *, VEC *b, VEC *x)
static Object ** m_zero(void *v)
Definition: matrix.cpp:512
static Object ** m_resize(void *v)
Definition: matrix.cpp:191
#define m_set_val(A, i, j, val)
Definition: matrix.h:277
#define VNULL
Definition: matrix.h:631
#define v_copy(in, out)
Definition: matrix.h:404
#define set_col(mat, col, vec)
Definition: matrix.h:564
#define set_row(mat, row, vec)
Definition: matrix.h:562
VEC * sv_mlt(double, VEC *, VEC *)
#define v_norm2(x)
Definition: matrix.h:511
#define v
Definition: md1redef.h:4
#define i
Definition: md1redef.h:12
#define TYPE_VEC
Definition: meminfo.h:52
#define MEM_STAT_REG(var, type)
Definition: meminfo.h:133
#define A(i)
Definition: multisplit.cpp:63
VEC * sp_mv_mlt(SPMAT *A, VEC *x, VEC *out)
Definition: sparse.c:123
Definition: matrix.h:73
u_int n
Definition: matrix.h:74
u_int m
Definition: matrix.h:74
Real ** me
Definition: matrix.h:76
Definition: sparse.h:54
Definition: matrix.h:67
u_int dim
Definition: matrix.h:68