NEURON
iternsym.c
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 
4 /**************************************************************************
5 **
6 ** Copyright (C) 1993 David E. Stewart & Zbigniew Leyk, all rights reserved.
7 **
8 ** Meschach Library
9 **
10 ** This Meschach Library is provided "as is" without any express
11 ** or implied warranty of any kind with respect to this software.
12 ** In particular the authors shall not be liable for any direct,
13 ** indirect, special, incidental or consequential damages arising
14 ** in any way from use of the software.
15 **
16 ** Everyone is granted permission to copy, modify and redistribute this
17 ** Meschach Library, provided:
18 ** 1. All copies contain this copyright notice.
19 ** 2. All modified copies shall carry a notice stating who
20 ** made the last modification and the date of such modification.
21 ** 3. No charge is made for this software or works derived from it.
22 ** This clause shall not be construed as constraining other software
23 ** distributed on the same medium as this software, nor is a
24 ** distribution fee considered a charge.
25 **
26 ***************************************************************************/
27 
28 
29 /* iter.c 17/09/93 */
30 
31 /*
32  ITERATIVE METHODS - implementation of several iterative methods;
33  see also iter0.c
34 */
35 
36 #include <stdio.h>
37 #include "matrix.h"
38 #include "matrix2.h"
39 #include "sparse.h"
40 #include "iter.h"
41 #include <math.h>
42 
43 static char rcsid[] = "iternsym.c,v 1.1 1997/12/04 17:55:27 hines Exp";
44 
45 
46 #ifdef ANSI_C
47 VEC *spCHsolve(SPMAT *,VEC *,VEC *);
48 #else
49 VEC *spCHsolve();
50 #endif
51 
52 
53 /*
54  iter_cgs -- uses CGS to compute a solution x to A.x=b
55 */
56 
57 VEC *iter_cgs(ip,r0)
58 ITER *ip;
59 VEC *r0;
60 {
61  static VEC *p = VNULL, *q = VNULL, *r = VNULL, *u = VNULL;
62  static VEC *v = VNULL, *z = VNULL;
63  VEC *tmp;
64  Real alpha, beta, nres, rho, old_rho, sigma, inner;
65 
66  if (ip == INULL)
67  error(E_NULL,"iter_cgs");
68  if (!ip->Ax || !ip->b || !r0)
69  error(E_NULL,"iter_cgs");
70  if ( ip->x == ip->b )
71  error(E_INSITU,"iter_cgs");
72  if (!ip->stop_crit)
73  error(E_NULL,"iter_cgs");
74  if ( r0->dim != ip->b->dim )
75  error(E_SIZES,"iter_cgs");
76 
77  if ( ip->eps <= 0.0 ) ip->eps = MACHEPS;
78 
79  p = v_resize(p,ip->b->dim);
80  q = v_resize(q,ip->b->dim);
81  r = v_resize(r,ip->b->dim);
82  u = v_resize(u,ip->b->dim);
83  v = v_resize(v,ip->b->dim);
84 
90 
91  if (ip->Bx) {
92  z = v_resize(z,ip->b->dim);
94  }
95 
96  if (ip->x != VNULL) {
97  if (ip->x->dim != ip->b->dim)
98  error(E_SIZES,"iter_cgs");
99  ip->Ax(ip->A_par,ip->x,v); /* v = A*x */
100  if (ip->Bx) {
101  v_sub(ip->b,v,v); /* v = b - A*x */
102  (ip->Bx)(ip->B_par,v,r); /* r = B*(b-A*x) */
103  }
104  else v_sub(ip->b,v,r); /* r = b-A*x */
105  }
106  else { /* ip->x == 0 */
107  ip->x = v_get(ip->b->dim); /* x == 0 */
108  ip->shared_x = FALSE;
109  if (ip->Bx) (ip->Bx)(ip->B_par,ip->b,r); /* r = B*b */
110  else v_copy(ip->b,r); /* r = b */
111  }
112 
113  v_zero(p);
114  v_zero(q);
115  old_rho = 1.0;
116 
117  for (ip->steps = 0; ip->steps <= ip->limit; ip->steps++) {
118 
119  inner = in_prod(r,r);
120  nres = sqrt(fabs(inner));
121  if (ip->steps == 0) ip->init_res = nres;
122 
123  if (ip->info) ip->info(ip,nres,r,VNULL);
124  if ( ip->stop_crit(ip,nres,r,VNULL) ) break;
125 
126  rho = in_prod(r0,r);
127  if ( old_rho == 0.0 )
128  error(E_BREAKDOWN,"iter_cgs");
129  beta = rho/old_rho;
130  v_mltadd(r,q,beta,u);
131  v_mltadd(q,p,beta,v);
132  v_mltadd(u,v,beta,p);
133 
134  (ip->Ax)(ip->A_par,p,q);
135  if (ip->Bx) {
136  (ip->Bx)(ip->B_par,q,z);
137  tmp = z;
138  }
139  else tmp = q;
140 
141  sigma = in_prod(r0,tmp);
142  if ( sigma == 0.0 )
143  error(E_BREAKDOWN,"iter_cgs");
144  alpha = rho/sigma;
145  v_mltadd(u,tmp,-alpha,q);
146  v_add(u,q,v);
147 
148  (ip->Ax)(ip->A_par,v,u);
149  if (ip->Bx) {
150  (ip->Bx)(ip->B_par,u,z);
151  tmp = z;
152  }
153  else tmp = u;
154 
155  v_mltadd(r,tmp,-alpha,r);
156  v_mltadd(ip->x,v,alpha,ip->x);
157 
158  old_rho = rho;
159  }
160 
161  return ip->x;
162 }
163 
164 
165 
166 /* iter_spcgs -- simple interface for SPMAT data structures
167  use always as follows:
168  x = iter_spcgs(A,B,b,r0,tol,x,limit,steps);
169  or
170  x = iter_spcgs(A,B,b,r0,tol,VNULL,limit,steps);
171  In the second case the solution vector is created.
172  If B is not NULL then it is a preconditioner.
173 */
175 SPMAT *A, *B;
176 VEC *b, *r0, *x;
177 double tol;
178 int *steps,limit;
179 {
180  ITER *ip;
181 
182  ip = iter_get(0,0);
183  ip->Ax = (Fun_Ax) sp_mv_mlt;
184  ip->A_par = (void *) A;
185  if (B) {
186  ip->Bx = (Fun_Ax) sp_mv_mlt;
187  ip->B_par = (void *) B;
188  }
189  else {
190  ip->Bx = (Fun_Ax) NULL;
191  ip->B_par = NULL;
192  }
193  ip->info = (Fun_info) NULL;
194  ip->limit = limit;
195  ip->b = b;
196  ip->eps = tol;
197  ip->x = x;
198  iter_cgs(ip,r0);
199  x = ip->x;
200  if (steps) *steps = ip->steps;
201  ip->shared_x = ip->shared_b = TRUE;
202  iter_free(ip); /* release only ITER structure */
203  return x;
204 
205 }
206 
207 /*
208  Routine for performing LSQR -- the least squares QR algorithm
209  of Paige and Saunders:
210  "LSQR: an algorithm for sparse linear equations and
211  sparse least squares", ACM Trans. Math. Soft., v. 8
212  pp. 43--71 (1982)
213  */
214 /* lsqr -- sparse CG-like least squares routine:
215  -- finds min_x ||A.x-b||_2 using A defined through A & AT
216  -- returns x (if x != NULL) */
218 ITER *ip;
219 {
220  static VEC *u = VNULL, *v = VNULL, *w = VNULL, *tmp = VNULL;
221  Real alpha, beta, phi, phi_bar;
222  Real rho, rho_bar, rho_max, theta, nres;
223  Real s, c; /* for Givens' rotations */
224  int m, n;
225 
226  if ( ! ip || ! ip->b || !ip->Ax || !ip->ATx )
227  error(E_NULL,"iter_lsqr");
228  if ( ip->x == ip->b )
229  error(E_INSITU,"iter_lsqr");
230  if (!ip->stop_crit || !ip->x)
231  error(E_NULL,"iter_lsqr");
232 
233  if ( ip->eps <= 0.0 ) ip->eps = MACHEPS;
234 
235  m = ip->b->dim;
236  n = ip->x->dim;
237 
238  u = v_resize(u,(u_int)m);
239  v = v_resize(v,(u_int)n);
240  w = v_resize(w,(u_int)n);
241  tmp = v_resize(tmp,(u_int)n);
242 
246  MEM_STAT_REG(tmp,TYPE_VEC);
247 
248  if (ip->x != VNULL) {
249  ip->Ax(ip->A_par,ip->x,u); /* u = A*x */
250  v_sub(ip->b,u,u); /* u = b-A*x */
251  }
252  else { /* ip->x == 0 */
253  ip->x = v_get(ip->b->dim);
254  ip->shared_x = FALSE;
255  v_copy(ip->b,u); /* u = b */
256  }
257 
258  beta = v_norm2(u);
259  if ( beta == 0.0 ) return ip->x;
260 
261  sv_mlt(1.0/beta,u,u);
262  (ip->ATx)(ip->AT_par,u,v);
263  alpha = v_norm2(v);
264  if ( alpha == 0.0 ) return ip->x;
265 
266  sv_mlt(1.0/alpha,v,v);
267  v_copy(v,w);
268  phi_bar = beta;
269  rho_bar = alpha;
270 
271  rho_max = 1.0;
272  for (ip->steps = 0; ip->steps <= ip->limit; ip->steps++) {
273 
274  tmp = v_resize(tmp,m);
275  (ip->Ax)(ip->A_par,v,tmp);
276 
277  v_mltadd(tmp,u,-alpha,u);
278  beta = v_norm2(u);
279  sv_mlt(1.0/beta,u,u);
280 
281  tmp = v_resize(tmp,n);
282  (ip->ATx)(ip->AT_par,u,tmp);
283  v_mltadd(tmp,v,-beta,v);
284  alpha = v_norm2(v);
285  sv_mlt(1.0/alpha,v,v);
286 
287  rho = sqrt(rho_bar*rho_bar+beta*beta);
288  if ( rho > rho_max )
289  rho_max = rho;
290  c = rho_bar/rho;
291  s = beta/rho;
292  theta = s*alpha;
293  rho_bar = -c*alpha;
294  phi = c*phi_bar;
295  phi_bar = s*phi_bar;
296 
297  /* update ip->x & w */
298  if ( rho == 0.0 )
299  error(E_BREAKDOWN,"iter_lsqr");
300  v_mltadd(ip->x,w,phi/rho,ip->x);
301  v_mltadd(v,w,-theta/rho,w);
302 
303  nres = fabs(phi_bar*alpha*c)*rho_max;
304 
305  if (ip->info) ip->info(ip,nres,w,VNULL);
306  if (ip->steps == 0) ip->init_res = nres;
307  if ( ip->stop_crit(ip,nres,w,VNULL) ) break;
308  }
309 
310  return ip->x;
311 }
312 
313 /* iter_splsqr -- simple interface for SPMAT data structures */
315 SPMAT *A;
316 VEC *b, *x;
317 double tol;
318 int *steps,limit;
319 {
320  ITER *ip;
321 
322  ip = iter_get(0,0);
323  ip->Ax = (Fun_Ax) sp_mv_mlt;
324  ip->A_par = (void *) A;
325  ip->ATx = (Fun_Ax) sp_vm_mlt;
326  ip->AT_par = (void *) A;
327  ip->Bx = (Fun_Ax) NULL;
328  ip->B_par = NULL;
329 
330  ip->info = (Fun_info) NULL;
331  ip->limit = limit;
332  ip->b = b;
333  ip->eps = tol;
334  ip->x = x;
335  iter_lsqr(ip);
336  x = ip->x;
337  if (steps) *steps = ip->steps;
338  ip->shared_x = ip->shared_b = TRUE;
339  iter_free(ip); /* release only ITER structure */
340  return x;
341 }
342 
343 
344 
345 /* iter_arnoldi -- an implementation of the Arnoldi method;
346  iterative refinement is applied.
347 */
348 MAT *iter_arnoldi_iref(ip,h_rem,Q,H)
349 ITER *ip;
350 Real *h_rem;
351 MAT *Q, *H;
352 {
353  static VEC *u=VNULL, *r=VNULL, *s=VNULL, *tmp=VNULL;
354  VEC v; /* auxiliary vector */
355  int i,j;
356  Real h_val, c;
357 
358  if (ip == INULL)
359  error(E_NULL,"iter_arnoldi_iref");
360  if ( ! ip->Ax || ! Q || ! ip->x )
361  error(E_NULL,"iter_arnoldi_iref");
362  if ( ip->k <= 0 )
363  error(E_BOUNDS,"iter_arnoldi_iref");
364  if ( Q->n != ip->x->dim || Q->m != ip->k )
365  error(E_SIZES,"iter_arnoldi_iref");
366 
367  m_zero(Q);
368  H = m_resize(H,ip->k,ip->k);
369  m_zero(H);
370 
371  u = v_resize(u,ip->x->dim);
372  r = v_resize(r,ip->k);
373  s = v_resize(s,ip->k);
374  tmp = v_resize(tmp,ip->x->dim);
378  MEM_STAT_REG(tmp,TYPE_VEC);
379 
380  v.dim = v.max_dim = ip->x->dim;
381 
382  c = v_norm2(ip->x);
383  if ( c <= 0.0)
384  return H;
385  else {
386  v.ve = Q->me[0];
387  sv_mlt(1.0/c,ip->x,&v);
388  }
389 
390  v_zero(r);
391  v_zero(s);
392  for ( i = 0; i < ip->k; i++ )
393  {
394  v.ve = Q->me[i];
395  u = (ip->Ax)(ip->A_par,&v,u);
396  for (j = 0; j <= i; j++) {
397  v.ve = Q->me[j];
398  /* modified Gram-Schmidt */
399  r->ve[j] = in_prod(&v,u);
400  v_mltadd(u,&v,-r->ve[j],u);
401  }
402  h_val = v_norm2(u);
403  /* if u == 0 then we have an exact subspace */
404  if ( h_val <= 0.0 )
405  {
406  *h_rem = h_val;
407  return H;
408  }
409  /* iterative refinement -- ensures near orthogonality */
410  do {
411  v_zero(tmp);
412  for (j = 0; j <= i; j++) {
413  v.ve = Q->me[j];
414  s->ve[j] = in_prod(&v,u);
415  v_mltadd(tmp,&v,s->ve[j],tmp);
416  }
417  v_sub(u,tmp,u);
418  v_add(r,s,r);
419  } while ( v_norm2(s) > 0.1*(h_val = v_norm2(u)) );
420  /* now that u is nearly orthogonal to Q, update H */
421  set_col(H,i,r);
422  /* check once again if h_val is zero */
423  if ( h_val <= 0.0 )
424  {
425  *h_rem = h_val;
426  return H;
427  }
428  if ( i == ip->k-1 )
429  {
430  *h_rem = h_val;
431  continue;
432  }
433  /* H->me[i+1][i] = h_val; */
434  m_set_val(H,i+1,i,h_val);
435  v.ve = Q->me[i+1];
436  sv_mlt(1.0/h_val,u,&v);
437  }
438 
439  return H;
440 }
441 
442 /* iter_arnoldi -- an implementation of the Arnoldi method;
443  modified Gram-Schmidt algorithm
444 */
445 MAT *iter_arnoldi(ip,h_rem,Q,H)
446 ITER *ip;
447 Real *h_rem;
448 MAT *Q, *H;
449 {
450  static VEC *u=VNULL, *r=VNULL;
451  VEC v; /* auxiliary vector */
452  int i,j;
453  Real h_val, c;
454 
455  if (ip == INULL)
456  error(E_NULL,"iter_arnoldi");
457  if ( ! ip->Ax || ! Q || ! ip->x )
458  error(E_NULL,"iter_arnoldi");
459  if ( ip->k <= 0 )
460  error(E_BOUNDS,"iter_arnoldi");
461  if ( Q->n != ip->x->dim || Q->m != ip->k )
462  error(E_SIZES,"iter_arnoldi");
463 
464  m_zero(Q);
465  H = m_resize(H,ip->k,ip->k);
466  m_zero(H);
467 
468  u = v_resize(u,ip->x->dim);
469  r = v_resize(r,ip->k);
472 
473  v.dim = v.max_dim = ip->x->dim;
474 
475  c = v_norm2(ip->x);
476  if ( c <= 0.0)
477  return H;
478  else {
479  v.ve = Q->me[0];
480  sv_mlt(1.0/c,ip->x,&v);
481  }
482 
483  v_zero(r);
484  for ( i = 0; i < ip->k; i++ )
485  {
486  v.ve = Q->me[i];
487  u = (ip->Ax)(ip->A_par,&v,u);
488  for (j = 0; j <= i; j++) {
489  v.ve = Q->me[j];
490  /* modified Gram-Schmidt */
491  r->ve[j] = in_prod(&v,u);
492  v_mltadd(u,&v,-r->ve[j],u);
493  }
494  h_val = v_norm2(u);
495  /* if u == 0 then we have an exact subspace */
496  if ( h_val <= 0.0 )
497  {
498  *h_rem = h_val;
499  return H;
500  }
501  set_col(H,i,r);
502  if ( i == ip->k-1 )
503  {
504  *h_rem = h_val;
505  continue;
506  }
507  /* H->me[i+1][i] = h_val; */
508  m_set_val(H,i+1,i,h_val);
509  v.ve = Q->me[i+1];
510  sv_mlt(1.0/h_val,u,&v);
511  }
512 
513  return H;
514 }
515 
516 
517 
518 /* iter_sparnoldi -- uses arnoldi() with an explicit representation of A */
519 MAT *iter_sparnoldi(A,x0,m,h_rem,Q,H)
520 SPMAT *A;
521 VEC *x0;
522 int m;
523 Real *h_rem;
524 MAT *Q, *H;
525 {
526  ITER *ip;
527 
528  ip = iter_get(0,0);
529  ip->Ax = (Fun_Ax) sp_mv_mlt;
530  ip->A_par = (void *) A;
531  ip->x = x0;
532  ip->k = m;
533  iter_arnoldi_iref(ip,h_rem,Q,H);
534  ip->shared_x = ip->shared_b = TRUE;
535  iter_free(ip); /* release only ITER structure */
536  return H;
537 }
538 
539 
540 /* for testing gmres */
541 static void test_gmres(ip,i,Q,R,givc,givs,h_val)
542 ITER *ip;
543 int i;
544 MAT *Q, *R;
545 VEC *givc, *givs;
546 double h_val;
547 {
548  VEC vt, vt1;
549  static MAT *Q1, *R1;
550  int j;
551 
552  /* test Q*A*Q^T = R */
553 
554  Q = m_resize(Q,i+1,ip->b->dim);
555  Q1 = m_resize(Q1,i+1,ip->b->dim);
556  R1 = m_resize(R1,i+1,i+1);
559 
560  vt.dim = vt.max_dim = ip->b->dim;
561  vt1.dim = vt1.max_dim = ip->b->dim;
562  for (j=0; j <= i; j++) {
563  vt.ve = Q->me[j];
564  vt1.ve = Q1->me[j];
565  ip->Ax(ip->A_par,&vt,&vt1);
566  }
567 
568  mmtr_mlt(Q,Q1,R1);
569  R1 = m_resize(R1,i+2,i+1);
570  for (j=0; j < i; j++)
571  R1->me[i+1][j] = 0.0;
572  R1->me[i+1][i] = h_val;
573 
574  for (j = 0; j <= i; j++) {
575  rot_rows(R1,j,j+1,givc->ve[j],givs->ve[j],R1);
576  }
577 
578  R1 = m_resize(R1,i+1,i+1);
579  m_sub(R,R1,R1);
580  /* if (m_norm_inf(R1) > MACHEPS*ip->b->dim) */
581  printf(" %d. ||Q*A*Q^T - H|| = %g [cf. MACHEPS = %g]\n",
582  ip->steps,m_norm_inf(R1),MACHEPS);
583 
584  /* check Q*Q^T = I */
585 
586  Q = m_resize(Q,i+1,ip->b->dim);
587  mmtr_mlt(Q,Q,R1);
588  for (j=0; j <= i; j++)
589  R1->me[j][j] -= 1.0;
590  if (m_norm_inf(R1) > MACHEPS*ip->b->dim)
591  printf(" ! m_norm_inf(Q*Q^T) = %g\n",m_norm_inf(R1));
592 
593 }
594 
595 
596 /* gmres -- generalised minimum residual algorithm of Saad & Schultz
597  SIAM J. Sci. Stat. Comp. v.7, pp.856--869 (1986)
598 */
600 ITER *ip;
601 {
602  static VEC *u=VNULL, *r=VNULL, *rhs = VNULL;
603  static VEC *givs=VNULL, *givc=VNULL, *z = VNULL;
604  static MAT *Q = MNULL, *R = MNULL;
605  VEC *rr, v, v1; /* additional pointers (not real vectors) */
606  int i,j, done;
607  Real nres;
608 /* Real last_h; */
609 
610  if (ip == INULL)
611  error(E_NULL,"iter_gmres");
612  if ( ! ip->Ax || ! ip->b )
613  error(E_NULL,"iter_gmres");
614  if ( ! ip->stop_crit )
615  error(E_NULL,"iter_gmres");
616  if ( ip->k <= 0 )
617  error(E_BOUNDS,"iter_gmres");
618  if (ip->x != VNULL && ip->x->dim != ip->b->dim)
619  error(E_SIZES,"iter_gmres");
620  if (ip->eps <= 0.0) ip->eps = MACHEPS;
621 
622  r = v_resize(r,ip->k+1);
623  u = v_resize(u,ip->b->dim);
624  rhs = v_resize(rhs,ip->k+1);
625  givs = v_resize(givs,ip->k); /* Givens rotations */
626  givc = v_resize(givc,ip->k);
627 
630  MEM_STAT_REG(rhs,TYPE_VEC);
631  MEM_STAT_REG(givs,TYPE_VEC);
632  MEM_STAT_REG(givc,TYPE_VEC);
633 
634  R = m_resize(R,ip->k+1,ip->k);
635  Q = m_resize(Q,ip->k,ip->b->dim);
638 
639  if (ip->x == VNULL) { /* ip->x == 0 */
640  ip->x = v_get(ip->b->dim);
641  ip->shared_x = FALSE;
642  }
643 
644  v.dim = v.max_dim = ip->b->dim; /* v and v1 are pointers to rows */
645  v1.dim = v1.max_dim = ip->b->dim; /* of matrix Q */
646 
647  if (ip->Bx != (Fun_Ax)NULL) { /* if precondition is defined */
648  z = v_resize(z,ip->b->dim);
650  }
651 
652  done = FALSE;
653  for (ip->steps = 0; ip->steps < ip->limit; ) {
654 
655  /* restart */
656 
657  ip->Ax(ip->A_par,ip->x,u); /* u = A*x */
658  v_sub(ip->b,u,u); /* u = b - A*x */
659  rr = u; /* rr is a pointer only */
660 
661  if (ip->Bx) {
662  (ip->Bx)(ip->B_par,u,z); /* tmp = B*(b-A*x) */
663  rr = z;
664  }
665 
666  nres = v_norm2(rr);
667  if (ip->steps == 0) {
668  if (ip->info) ip->info(ip,nres,VNULL,VNULL);
669  ip->init_res = nres;
670  }
671 
672  if ( nres == 0.0 ) {
673  done = TRUE;
674  break;
675  }
676 
677  v.ve = Q->me[0];
678  sv_mlt(1.0/nres,rr,&v);
679 
680  v_zero(r);
681  v_zero(rhs);
682  rhs->ve[0] = nres;
683 
684  for ( i = 0; i < ip->k && ip->steps < ip->limit; i++ ) {
685  ip->steps++;
686  v.ve = Q->me[i];
687  (ip->Ax)(ip->A_par,&v,u);
688  rr = u;
689  if (ip->Bx) {
690  (ip->Bx)(ip->B_par,u,z);
691  rr = z;
692  }
693 
694  if (i < ip->k - 1) {
695  v1.ve = Q->me[i+1];
696  v_copy(rr,&v1);
697  for (j = 0; j <= i; j++) {
698  v.ve = Q->me[j];
699  /* r->ve[j] = in_prod(&v,rr); */
700  /* modified Gram-Schmidt algorithm */
701  r->ve[j] = in_prod(&v,&v1);
702  v_mltadd(&v1,&v,-r->ve[j],&v1);
703  }
704 
705  r->ve[i+1] = nres = v_norm2(&v1);
706  if (nres <= MACHEPS*ip->init_res) {
707  for (j = 0; j < i; j++)
708  rot_vec(r,j,j+1,givc->ve[j],givs->ve[j],r);
709  set_col(R,i,r);
710  done = TRUE;
711  break;
712  }
713  sv_mlt(1.0/nres,&v1,&v1);
714  }
715  else { /* i == ip->k - 1 */
716  /* Q->me[ip->k] need not be computed */
717 
718  for (j = 0; j <= i; j++) {
719  v.ve = Q->me[j];
720  r->ve[j] = in_prod(&v,rr);
721  }
722 
723  nres = in_prod(rr,rr) - in_prod(r,r);
724  if (sqrt(fabs(nres)) <= MACHEPS*ip->init_res) {
725  for (j = 0; j < i; j++)
726  rot_vec(r,j,j+1,givc->ve[j],givs->ve[j],r);
727  set_col(R,i,r);
728  done = TRUE;
729  break;
730  }
731  if (nres < 0.0) { /* do restart */
732  i--;
733  ip->steps--;
734  break;
735  }
736  r->ve[i+1] = sqrt(nres);
737  }
738 
739  /* QR update */
740 
741  /* last_h = r->ve[i+1]; */ /* for test only */
742  for (j = 0; j < i; j++)
743  rot_vec(r,j,j+1,givc->ve[j],givs->ve[j],r);
744  givens(r->ve[i],r->ve[i+1],&givc->ve[i],&givs->ve[i]);
745  rot_vec(r,i,i+1,givc->ve[i],givs->ve[i],r);
746  rot_vec(rhs,i,i+1,givc->ve[i],givs->ve[i],rhs);
747 
748  set_col(R,i,r);
749 
750  nres = fabs((double) rhs->ve[i+1]);
751  if (ip->info) ip->info(ip,nres,VNULL,VNULL);
752  if ( ip->stop_crit(ip,nres,VNULL,VNULL) ) {
753  done = TRUE;
754  break;
755  }
756  }
757 
758  /* use ixi submatrix of R */
759 
760  if (i >= ip->k) i = ip->k - 1;
761 
762  R = m_resize(R,i+1,i+1);
763  rhs = v_resize(rhs,i+1);
764 
765  /* test only */
766  /* test_gmres(ip,i,Q,R,givc,givs,last_h); */
767 
768  Usolve(R,rhs,rhs,0.0); /* solve a system: R*x = rhs */
769 
770  /* new approximation */
771 
772  for (j = 0; j <= i; j++) {
773  v.ve = Q->me[j];
774  v_mltadd(ip->x,&v,rhs->ve[j],ip->x);
775  }
776 
777  if (done) break;
778 
779  /* back to old dimensions */
780 
781  rhs = v_resize(rhs,ip->k+1);
782  R = m_resize(R,ip->k+1,ip->k);
783 
784  }
785 
786  return ip->x;
787 }
788 
789 /* iter_spgmres - a simple interface to iter_gmres */
790 
792 SPMAT *A, *B;
793 VEC *b, *x;
794 double tol;
795 int *steps,k,limit;
796 {
797  ITER *ip;
798 
799  ip = iter_get(0,0);
800  ip->Ax = (Fun_Ax) sp_mv_mlt;
801  ip->A_par = (void *) A;
802  if (B) {
803  ip->Bx = (Fun_Ax) sp_mv_mlt;
804  ip->B_par = (void *) B;
805  }
806  else {
807  ip->Bx = (Fun_Ax) NULL;
808  ip->B_par = NULL;
809  }
810  ip->k = k;
811  ip->limit = limit;
812  ip->info = (Fun_info) NULL;
813  ip->b = b;
814  ip->eps = tol;
815  ip->x = x;
816  iter_gmres(ip);
817  x = ip->x;
818  if (steps) *steps = ip->steps;
819  ip->shared_x = ip->shared_b = TRUE;
820  iter_free(ip); /* release only ITER structure */
821  return x;
822 }
823 
824 
825 /* for testing mgcr */
826 static void test_mgcr(ip,i,Q,R)
827 ITER *ip;
828 int i;
829 MAT *Q, *R;
830 {
831  VEC vt, vt1;
832  static MAT *R1;
833  static VEC *r, *r1;
834  VEC *rr;
835  int k,j;
836  Real sm;
837 
838 
839  /* check Q*Q^T = I */
840  vt.dim = vt.max_dim = ip->b->dim;
841  vt1.dim = vt1.max_dim = ip->b->dim;
842 
843  Q = m_resize(Q,i+1,ip->b->dim);
844  R1 = m_resize(R1,i+1,i+1);
845  r = v_resize(r,ip->b->dim);
846  r1 = v_resize(r1,ip->b->dim);
850 
851  m_zero(R1);
852  for (k=1; k <= i; k++)
853  for (j=1; j <= i; j++) {
854  vt.ve = Q->me[k];
855  vt1.ve = Q->me[j];
856  R1->me[k][j] = in_prod(&vt,&vt1);
857  }
858  for (j=1; j <= i; j++)
859  R1->me[j][j] -= 1.0;
860  if (m_norm_inf(R1) > MACHEPS*ip->b->dim)
861  printf(" ! (mgcr:) m_norm_inf(Q*Q^T) = %g\n",m_norm_inf(R1));
862 
863  /* check (r_i,Ap_j) = 0 for j <= i */
864 
865  ip->Ax(ip->A_par,ip->x,r);
866  v_sub(ip->b,r,r);
867  rr = r;
868  if (ip->Bx) {
869  ip->Bx(ip->B_par,r,r1);
870  rr = r1;
871  }
872 
873  printf(" ||r|| = %g\n",v_norm2(rr));
874  sm = 0.0;
875  for (j = 1; j <= i; j++) {
876  vt.ve = Q->me[j];
877  sm = max(sm,in_prod(&vt,rr));
878  }
879  if (sm >= MACHEPS*ip->b->dim)
880  printf(" ! (mgcr:) max_j (r,Ap_j) = %g\n",sm);
881 
882 }
883 
884 
885 
886 
887 /*
888  iter_mgcr -- modified generalized conjugate residual algorithm;
889  fast version of GCR;
890 */
892 ITER *ip;
893 {
894  static VEC *As, *beta, *alpha, *z;
895  static MAT *N, *H;
896 
897  VEC *rr, v, s; /* additional pointer and structures */
898  Real nres; /* norm of a residual */
899  Real dd; /* coefficient d_i */
900  int i,j;
901  int done; /* if TRUE then stop the iterative process */
902  int dim; /* dimension of the problem */
903 
904  /* ip cannot be NULL */
905  if (ip == INULL) error(E_NULL,"mgcr");
906  /* Ax, b and stopping criterion must be given */
907  if (! ip->Ax || ! ip->b || ! ip->stop_crit)
908  error(E_NULL,"mgcr");
909  /* at least one direction vector must exist */
910  if ( ip->k <= 0) error(E_BOUNDS,"mgcr");
911  /* if the vector x is given then b and x must have the same dimension */
912  if ( ip->x && ip->x->dim != ip->b->dim)
913  error(E_SIZES,"mgcr");
914  if (ip->eps <= 0.0) ip->eps = MACHEPS;
915 
916  dim = ip->b->dim;
917  As = v_resize(As,dim);
918  alpha = v_resize(alpha,ip->k);
919  beta = v_resize(beta,ip->k);
920 
922  MEM_STAT_REG(alpha,TYPE_VEC);
923  MEM_STAT_REG(beta,TYPE_VEC);
924 
925  H = m_resize(H,ip->k,ip->k);
926  N = m_resize(N,ip->k,dim);
927 
930 
931  /* if a preconditioner is defined */
932  if (ip->Bx) {
933  z = v_resize(z,dim);
935  }
936 
937  /* if x is NULL then it is assumed that x has
938  entries with value zero */
939  if ( ! ip->x ) {
940  ip->x = v_get(ip->b->dim);
941  ip->shared_x = FALSE;
942  }
943 
944  /* v and s are additional pointers to rows of N */
945  /* they must have the same dimension as rows of N */
946  v.dim = v.max_dim = s.dim = s.max_dim = dim;
947 
948 
949  done = FALSE;
950  for (ip->steps = 0; ip->steps < ip->limit; ) {
951  (*ip->Ax)(ip->A_par,ip->x,As); /* As = A*x */
952  v_sub(ip->b,As,As); /* As = b - A*x */
953  rr = As; /* rr is an additional pointer */
954 
955  /* if a preconditioner is defined */
956  if (ip->Bx) {
957  (*ip->Bx)(ip->B_par,As,z); /* z = B*(b-A*x) */
958  rr = z;
959  }
960 
961  /* norm of the residual */
962  nres = v_norm2(rr);
963  dd = nres; /* dd = ||r_i|| */
964 
965  /* check if the norm of the residual is zero */
966  if (ip->steps == 0) {
967  /* information for a user */
968  if (ip->info) (*ip->info)(ip,nres,As,rr);
969  ip->init_res = fabs(nres);
970  }
971 
972  if (nres == 0.0) {
973  /* iterative process is finished */
974  done = TRUE;
975  break;
976  }
977 
978  /* save this residual in the first row of N */
979  v.ve = N->me[0];
980  v_copy(rr,&v);
981 
982  for (i = 0; i < ip->k && ip->steps < ip->limit; i++) {
983  ip->steps++;
984  v.ve = N->me[i]; /* pointer to a row of N (=s_i) */
985  /* note that we must use here &v, not v */
986  (*ip->Ax)(ip->A_par,&v,As);
987  rr = As; /* As = A*s_i */
988  if (ip->Bx) {
989  (*ip->Bx)(ip->B_par,As,z); /* z = B*A*s_i */
990  rr = z;
991  }
992 
993  if (i < ip->k - 1) {
994  s.ve = N->me[i+1]; /* pointer to a row of N (=s_{i+1}) */
995  v_copy(rr,&s); /* s_{i+1} = B*A*s_i */
996  for (j = 0; j <= i-1; j++) {
997  v.ve = N->me[j+1]; /* pointer to a row of N (=s_{j+1}) */
998  /* beta->ve[j] = in_prod(&v,rr); */ /* beta_{j,i} */
999  /* modified Gram-Schmidt algorithm */
1000  beta->ve[j] = in_prod(&v,&s); /* beta_{j,i} */
1001  /* s_{i+1} -= beta_{j,i}*s_{j+1} */
1002  v_mltadd(&s,&v,- beta->ve[j],&s);
1003  }
1004 
1005  /* beta_{i,i} = ||s_{i+1}||_2 */
1006  beta->ve[i] = nres = v_norm2(&s);
1007  if ( nres <= MACHEPS*ip->init_res) {
1008  /* s_{i+1} == 0 */
1009  i--;
1010  done = TRUE;
1011  break;
1012  }
1013  sv_mlt(1.0/nres,&s,&s); /* normalize s_{i+1} */
1014 
1015  v.ve = N->me[0];
1016  alpha->ve[i] = in_prod(&v,&s); /* alpha_i = (s_0 , s_{i+1}) */
1017 
1018  }
1019  else {
1020  for (j = 0; j <= i-1; j++) {
1021  v.ve = N->me[j+1]; /* pointer to a row of N (=s_{j+1}) */
1022  beta->ve[j] = in_prod(&v,rr); /* beta_{j,i} */
1023  }
1024 
1025  nres = in_prod(rr,rr); /* rr = B*A*s_{k-1} */
1026  for (j = 0; j <= i-1; j++)
1027  nres -= beta->ve[j]*beta->ve[j];
1028 
1029  if (sqrt(fabs(nres)) <= MACHEPS*ip->init_res) {
1030  /* s_k is zero */
1031  i--;
1032  done = TRUE;
1033  break;
1034  }
1035  if (nres < 0.0) { /* do restart */
1036  i--;
1037  ip->steps--;
1038  break;
1039  }
1040  beta->ve[i] = sqrt(nres); /* beta_{k-1,k-1} */
1041 
1042  v.ve = N->me[0];
1043  alpha->ve[i] = in_prod(&v,rr);
1044  for (j = 0; j <= i-1; j++)
1045  alpha->ve[i] -= beta->ve[j]*alpha->ve[j];
1046  alpha->ve[i] /= beta->ve[i]; /* alpha_{k-1} */
1047 
1048  }
1049 
1050  set_col(H,i,beta);
1051 
1052  /* other method of computing dd */
1053  /* if (fabs((double)alpha->ve[i]) > dd) {
1054  nres = - dd*dd + alpha->ve[i]*alpha->ve[i];
1055  nres = sqrt((double) nres);
1056  if (ip->info) (*ip->info)(ip,-nres,VNULL,VNULL);
1057  break;
1058  } */
1059  /* to avoid overflow/underflow in computing dd */
1060  /* dd *= cos(asin((double)(alpha->ve[i]/dd))); */
1061 
1062  nres = alpha->ve[i]/dd;
1063  if (fabs(nres-1.0) <= MACHEPS*ip->init_res)
1064  dd = 0.0;
1065  else {
1066  nres = 1.0 - nres*nres;
1067  if (nres < 0.0) {
1068  nres = sqrt((double) -nres);
1069  if (ip->info) (*ip->info)(ip,-dd*nres,VNULL,VNULL);
1070  break;
1071  }
1072  dd *= sqrt((double) nres);
1073  }
1074 
1075  if (ip->info) (*ip->info)(ip,dd,VNULL,VNULL);
1076  if ( ip->stop_crit(ip,dd,VNULL,VNULL) ) {
1077  /* stopping criterion is satisfied */
1078  done = TRUE;
1079  break;
1080  }
1081 
1082  } /* end of for */
1083 
1084  if (i >= ip->k) i = ip->k - 1;
1085 
1086  /* use (i+1) by (i+1) submatrix of H */
1087  H = m_resize(H,i+1,i+1);
1088  alpha = v_resize(alpha,i+1);
1089  Usolve(H,alpha,alpha,0.0); /* c_i is saved in alpha */
1090 
1091  for (j = 0; j <= i; j++) {
1092  v.ve = N->me[j];
1093  v_mltadd(ip->x,&v,alpha->ve[j],ip->x);
1094  }
1095 
1096 
1097  if (done) break; /* stop the iterative process */
1098  alpha = v_resize(alpha,ip->k);
1099  H = m_resize(H,ip->k,ip->k);
1100 
1101  } /* end of while */
1102 
1103  return ip->x; /* return the solution */
1104 }
1105 
1106 
1107 
1108 /* iter_spmgcr - a simple interface to iter_mgcr */
1109 /* no preconditioner */
1111 SPMAT *A, *B;
1112 VEC *b, *x;
1113 double tol;
1114 int *steps,k,limit;
1115 {
1116  ITER *ip;
1117 
1118  ip = iter_get(0,0);
1119  ip->Ax = (Fun_Ax) sp_mv_mlt;
1120  ip->A_par = (void *) A;
1121  if (B) {
1122  ip->Bx = (Fun_Ax) sp_mv_mlt;
1123  ip->B_par = (void *) B;
1124  }
1125  else {
1126  ip->Bx = (Fun_Ax) NULL;
1127  ip->B_par = NULL;
1128  }
1129 
1130  ip->k = k;
1131  ip->limit = limit;
1132  ip->info = (Fun_info) NULL;
1133  ip->b = b;
1134  ip->eps = tol;
1135  ip->x = x;
1136  iter_mgcr(ip);
1137  x = ip->x;
1138  if (steps) *steps = ip->steps;
1139  ip->shared_x = ip->shared_b = TRUE;
1140  iter_free(ip); /* release only ITER structure */
1141  return x;
1142 }
1143 
1144 
1145 
1146 /*
1147  Conjugate gradients method for a normal equation
1148  a preconditioner B must be symmetric !!
1149 */
1151 ITER *ip;
1152 {
1153  static VEC *r = VNULL, *p = VNULL, *q = VNULL, *z = VNULL;
1154  Real alpha, beta, inner, old_inner, nres;
1155  VEC *rr1; /* pointer only */
1156 
1157  if (ip == INULL)
1158  error(E_NULL,"iter_cgne");
1159  if (!ip->Ax || ! ip->ATx || !ip->b)
1160  error(E_NULL,"iter_cgne");
1161  if ( ip->x == ip->b )
1162  error(E_INSITU,"iter_cgne");
1163  if (!ip->stop_crit)
1164  error(E_NULL,"iter_cgne");
1165 
1166  if ( ip->eps <= 0.0 ) ip->eps = MACHEPS;
1167 
1168  r = v_resize(r,ip->b->dim);
1169  p = v_resize(p,ip->b->dim);
1170  q = v_resize(q,ip->b->dim);
1171 
1175 
1176  z = v_resize(z,ip->b->dim);
1178 
1179  if (ip->x) {
1180  if (ip->x->dim != ip->b->dim)
1181  error(E_SIZES,"iter_cgne");
1182  ip->Ax(ip->A_par,ip->x,p); /* p = A*x */
1183  v_sub(ip->b,p,z); /* z = b - A*x */
1184  }
1185  else { /* ip->x == 0 */
1186  ip->x = v_get(ip->b->dim);
1187  ip->shared_x = FALSE;
1188  v_copy(ip->b,z);
1189  }
1190  rr1 = z;
1191  if (ip->Bx) {
1192  (ip->Bx)(ip->B_par,rr1,p);
1193  rr1 = p;
1194  }
1195  (ip->ATx)(ip->AT_par,rr1,r); /* r = A^T*B*(b-A*x) */
1196 
1197 
1198  old_inner = 0.0;
1199  for ( ip->steps = 0; ip->steps <= ip->limit; ip->steps++ )
1200  {
1201  rr1 = r;
1202  if ( ip->Bx ) {
1203  (ip->Bx)(ip->B_par,r,z); /* rr = B*r */
1204  rr1 = z;
1205  }
1206 
1207  inner = in_prod(r,rr1);
1208  nres = sqrt(fabs(inner));
1209  if (ip->info) ip->info(ip,nres,r,rr1);
1210  if (ip->steps == 0) ip->init_res = nres;
1211  if ( ip->stop_crit(ip,nres,r,rr1) ) break;
1212 
1213  if ( ip->steps ) /* if ( ip->steps > 0 ) ... */
1214  {
1215  beta = inner/old_inner;
1216  p = v_mltadd(rr1,p,beta,p);
1217  }
1218  else /* if ( ip->steps == 0 ) ... */
1219  {
1220  beta = 0.0;
1221  p = v_copy(rr1,p);
1222  old_inner = 0.0;
1223  }
1224  (ip->Ax)(ip->A_par,p,q); /* q = A*p */
1225  if (ip->Bx) {
1226  (ip->Bx)(ip->B_par,q,z);
1227  (ip->ATx)(ip->AT_par,z,q);
1228  rr1 = q; /* q = A^T*B*A*p */
1229  }
1230  else {
1231  (ip->ATx)(ip->AT_par,q,z); /* z = A^T*A*p */
1232  rr1 = z;
1233  }
1234 
1235  alpha = inner/in_prod(rr1,p);
1236  v_mltadd(ip->x,p,alpha,ip->x);
1237  v_mltadd(r,rr1,-alpha,r);
1238  old_inner = inner;
1239  }
1240 
1241  return ip->x;
1242 }
1243 
1244 /* iter_spcgne -- a simple interface to iter_cgne() which
1245  uses sparse matrix data structures
1246  -- assumes that B contains an actual preconditioner (or NULL)
1247  use always as follows:
1248  x = iter_spcgne(A,B,b,eps,x,limit,steps);
1249  or
1250  x = iter_spcgne(A,B,b,eps,VNULL,limit,steps);
1251  In the second case the solution vector is created.
1252 */
1254 SPMAT *A, *B;
1255 VEC *b, *x;
1256 double eps;
1257 int *steps, limit;
1258 {
1259  ITER *ip;
1260 
1261  ip = iter_get(0,0);
1262  ip->Ax = (Fun_Ax) sp_mv_mlt;
1263  ip->A_par = (void *)A;
1264  ip->ATx = (Fun_Ax) sp_vm_mlt;
1265  ip->AT_par = (void *)A;
1266  if (B) {
1267  ip->Bx = (Fun_Ax) sp_mv_mlt;
1268  ip->B_par = (void *)B;
1269  }
1270  else {
1271  ip->Bx = (Fun_Ax) NULL;
1272  ip->B_par = NULL;
1273  }
1274  ip->info = (Fun_info) NULL;
1275  ip->b = b;
1276  ip->eps = eps;
1277  ip->limit = limit;
1278  ip->x = x;
1279  iter_cgne(ip);
1280  x = ip->x;
1281  if (steps) *steps = ip->steps;
1282  ip->shared_x = ip->shared_b = TRUE;
1283  iter_free(ip); /* release only ITER structure */
1284  return x;
1285 }
1286 
1287 
1288 
MAT * mmtr_mlt(MAT *A, MAT *B, MAT *OUT)
Definition: matop.c:134
Fun_Ax Ax
Definition: iter.h:68
MAT * rot_rows(MAT *mat, u_int i, u_int k, double c, double s, MAT *out)
Definition: givens.c:85
double max(double a, double b)
Definition: geometry3d.cpp:22
#define B(i)
Definition: multisplit.cpp:62
void(* info)()
Definition: iter.h:92
VEC * iter_gmres(ITER *ip)
Definition: iternsym.c:599
if(status)
VEC * iter_splsqr(SPMAT *A, VEC *b, double tol, VEC *x, int limit, int *steps)
Definition: iternsym.c:314
unsigned k
Definition: iter.h:59
#define TYPE_VEC
Definition: meminfo.h:52
VEC * iter_lsqr(ITER *ip)
Definition: iternsym.c:217
#define in_prod(a, b)
Definition: matrix.h:485
#define Real
Definition: machine.h:189
static Object ** v_resize(void *v)
Definition: ivocvect.cpp:1297
size_t p
#define TRUE
Definition: err.c:57
#define m_set_val(A, i, j, val)
Definition: matrix.h:277
static void test_gmres(ITER *ip, int i, MAT *Q, MAT *R, VEC *givc, VEC *givs, double h_val)
Definition: iternsym.c:541
#define v_norm2(x)
Definition: matrix.h:511
double m_norm_inf(MAT *A)
#define v
Definition: md1redef.h:4
int iter_free(ITER *ip)
Definition: iter0.c:118
static philox4x32_key_t k
Definition: nrnran123.cpp:11
u_int n
Definition: matrix.h:74
int shared_b
Definition: iter.h:58
int steps
Definition: iter.h:61
MAT * iter_sparnoldi(SPMAT *A, VEC *x0, int m, Real *h_rem, MAT *Q, MAT *H)
Definition: iternsym.c:519
ITER * iter_get(int lenb, int lenx)
Definition: iter0.c:76
Real * ve
Definition: matrix.h:69
Real init_res
Definition: iter.h:108
VEC * iter_spgmres(SPMAT *A, SPMAT *B, VEC *b, double tol, VEC *x, int k, int limit, int *steps)
Definition: iternsym.c:791
Definition: matrix.h:67
static double done(void *v)
Definition: ocbbs.cpp:280
static Object ** v_sub(void *v1)
Definition: ivocvect.cpp:2263
VEC * iter_spmgcr(SPMAT *A, SPMAT *B, VEC *b, double tol, VEC *x, int k, int limit, int *steps)
Definition: iternsym.c:1110
#define v_copy(in, out)
Definition: matrix.h:404
#define E_SIZES
Definition: err.h:95
uint32_t u_int
Definition: machine.h:38
Definition: sparse.h:54
int const size_t const size_t n
Definition: nrngsl.h:12
_CONST char * s
Definition: system.cpp:74
#define MNULL
Definition: matrix.h:632
#define printf
Definition: mwprefix.h:26
u_int dim
Definition: matrix.h:68
void givens(double x, double y, Real *c, Real *s)
Definition: givens.c:47
#define INULL
Definition: iter.h:113
Fun_Ax Bx
Definition: iter.h:75
static char rcsid[]
Definition: iternsym.c:43
VEC *(* Fun_Ax)(void *, VEC *, VEC *)
Definition: iter.h:49
#define E_BOUNDS
Definition: err.h:96
VEC * v_mltadd(VEC *, VEC *, double, VEC *)
#define E_NULL
Definition: err.h:102
size_t j
#define alpha
Definition: bkpfacto.c:43
#define set_col(mat, col, vec)
Definition: matrix.h:564
VEC * iter_cgne(ITER *ip)
Definition: iternsym.c:1150
int limit
Definition: iter.h:60
VEC * sv_mlt(double, VEC *, VEC *)
VEC * spCHsolve(SPMAT *, VEC *, VEC *)
Definition: spchfctr.c:311
VEC * sp_mv_mlt(SPMAT *A, VEC *x, VEC *out)
Definition: sparse.c:123
static double v_get(void *v)
Definition: ivocvect.cpp:1309
VEC * Usolve(MAT *A, VEC *b, VEC *x, double diag_val)
#define MACHEPS
Definition: machine.h:213
void * AT_par
Definition: iter.h:73
#define rhs
Definition: lineq.h:6
VEC * iter_mgcr(ITER *ip)
Definition: iternsym.c:891
VEC * rot_vec(VEC *x, u_int i, u_int k, double c, double s, VEC *out)
Definition: givens.c:61
VEC * v_zero(VEC *x)
Definition: init.c:40
VEC * iter_cgs(ITER *ip, VEC *r0)
Definition: iternsym.c:57
int shared_x
Definition: iter.h:57
u_int max_dim
Definition: matrix.h:68
MAT * iter_arnoldi_iref(ITER *ip, Real *h_rem, MAT *Q, MAT *H)
Definition: iternsym.c:348
sqrt
Definition: extdef.h:3
Real eps
Definition: iter.h:62
static Object ** v_add(void *v1)
Definition: ivocvect.cpp:2245
#define E_BREAKDOWN
Definition: err.h:116
static Object ** m_resize(void *v)
Definition: matrix.cpp:190
#define MEM_STAT_REG(var, type)
Definition: meminfo.h:133
#define FALSE
Definition: err.c:56
#define i
Definition: md1redef.h:12
#define A(i)
Definition: multisplit.cpp:61
#define c
static Object ** m_zero(void *v)
Definition: matrix.cpp:511
#define error(err_num, fn_name)
Definition: err.h:73
fabs
Definition: extdef.h:3
u_int m
Definition: matrix.h:74
void(* Fun_info)(ITER *, double, VEC *, VEC *)
Definition: iter.h:117
VEC * x
Definition: iter.h:64
#define TYPE_MAT
Definition: meminfo.h:49
#define VNULL
Definition: matrix.h:631
Fun_Ax ATx
Definition: iter.h:71
VEC * iter_spcgs(SPMAT *A, SPMAT *B, VEC *b, VEC *r0, double tol, VEC *x, int limit, int *steps)
Definition: iternsym.c:174
for(i=0;i< n;i++)
size_t q
MAT * iter_arnoldi(ITER *ip, Real *h_rem, MAT *Q, MAT *H)
Definition: iternsym.c:445
VEC * iter_spcgne(SPMAT *A, SPMAT *B, VEC *b, double eps, VEC *x, int limit, int *steps)
Definition: iternsym.c:1253
void * B_par
Definition: iter.h:76
return NULL
Definition: cabcode.cpp:461
Definition: iter.h:56
Real ** me
Definition: matrix.h:76
Definition: matrix.h:73
void * A_par
Definition: iter.h:69
MAT * m_sub(MAT *mat1, MAT *mat2, MAT *out)
Definition: matop.c:63
VEC * b
Definition: iter.h:66
static void test_mgcr(ITER *ip, int i, MAT *Q, MAT *R)
Definition: iternsym.c:826
#define E_INSITU
Definition: err.h:106
VEC * sp_vm_mlt(SPMAT *A, VEC *x, VEC *out)
Definition: sparse.c:159