OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
subspaceit.C
Go to the documentation of this file.
1 /*
2  *
3  * ##### ##### ###### ###### ### ###
4  * ## ## ## ## ## ## ## ### ##
5  * ## ## ## ## #### #### ## # ##
6  * ## ## ## ## ## ## ## ##
7  * ## ## ## ## ## ## ## ##
8  * ##### ##### ## ###### ## ##
9  *
10  *
11  * OOFEM : Object Oriented Finite Element Code
12  *
13  * Copyright (C) 1993 - 2013 Borek Patzak
14  *
15  *
16  *
17  * Czech Technical University, Faculty of Civil Engineering,
18  * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19  *
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33  */
34 
35 //#define DETAILED_REPORT
36 
37 #include "subspaceit.h"
38 #include "engngm.h"
39 #include "domain.h"
40 #include "floatmatrix.h"
41 #include "floatarray.h"
42 #include "mathfem.h"
43 #include "gjacobi.h"
44 #include "sparselinsystemnm.h"
45 #include "classfactory.h"
46 
47 namespace oofem {
49 
52 {
53  nitem = 40; // max number of iterations
54 }
55 
56 
58 { }
59 
61 SubspaceIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, FloatMatrix &_r, double rtol, int nroot)
62 //
63 // this function solve the generalized eigenproblem using the Generalized
64 // jacobi iteration
65 //
66 {
67  if ( a.giveNumberOfColumns() != b.giveNumberOfColumns() ) {
68  OOFEM_ERROR("matrices size mismatch");
69  }
70 
71  FloatArray temp, w, d, tt, f, rtolv, eigv;
72  FloatMatrix r;
73  int nn, nc1, ij = 0, is;
74  double rt, art, brt, eigvt;
75  FloatMatrix ar, br, vec;
76  std :: unique_ptr< SparseLinearSystemNM > solver( GiveClassFactory().createSparseLinSolver(ST_Direct, domain, engngModel) );
77 
79  int nc = min(2 * nroot, nroot + 8);
80  nn = a.giveNumberOfColumns();
81  if ( nc > nn ) {
82  nc = nn;
83  }
84 
85  ar.resize(nc, nc);
86  ar.zero();
87  br.resize(nc, nc);
88  br.zero();
89 
90  //
91  // creation of initial iteration vectors
92  //
93  nc1 = nc - 1;
94 
95  w.resize(nn);
96  w.zero();
97  d.resize(nc);
98  d.zero();
99  tt.resize(nn);
100  tt.zero();
101  rtolv.resize(nc);
102  rtolv.zero();
103  vec.resize(nc, nc);
104  vec.zero(); // eigen vectors of reduced problem
105 
106  //
107  // create work arrays
108  //
109  r.resize(nn, nc);
110  r.zero();
111  eigv.resize(nc);
112  eigv.zero();
113 
114  FloatArray h(nn);
115  for ( int i = 1; i <= nn; i++ ) {
116  h.at(i) = 1.0;
117  w.at(i) = b.at(i, i) / a.at(i, i);
118  }
119 
120  b.times(h, tt);
121  r.setColumn(tt, 1);
122 
123  for ( int j = 2; j <= nc; j++ ) {
124  rt = 0.0;
125  for ( int i = 1; i <= nn; i++ ) {
126  if ( fabs( w.at(i) ) >= rt ) {
127  rt = fabs( w.at(i) );
128  ij = i;
129  }
130  }
131 
132  tt.at(j) = ij;
133  w.at(ij) = 0.;
134  for ( int i = 1; i <= nn; i++ ) {
135  if ( i == ij ) {
136  h.at(i) = 1.0;
137  } else {
138  h.at(i) = 0.0;
139  }
140  }
141 
142  b.times(h, tt);
143  r.setColumn(tt, j);
144  } // (r = z)
145 
146 # ifdef DETAILED_REPORT
147  OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Degrees of freedom invoked by initial vectors :\n");
148  tt.printYourself();
149  OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: initial vectors for iteration:\n");
150  r.printYourself();
151 # endif
152 
153  //ish = 0;
154  a.factorized();
155  //
156  // start of iteration loop
157  //
158  for ( int nite = 0; ; ++nite ) { // label 100
159 # ifdef DETAILED_REPORT
160  printf("SubspaceIteration :: solveYourselfAt: Iteration loop no. %d\n", nite);
161 # endif
162  //
163  // compute projection ar and br of matrices a , b
164  //
165  for ( int j = 1; j <= nc; j++ ) {
166  f.beColumnOf(r, j);
167 
168  solver->solve(a, f, tt);
169 
170  for ( int i = j; i <= nc; i++ ) {
171  art = 0.;
172  for ( int k = 1; k <= nn; k++ ) {
173  art += r.at(k, i) * tt.at(k);
174  }
175 
176  ar.at(j, i) = art;
177  }
178 
179  r.setColumn(tt, j); // (r = xbar)
180  }
181 
182  ar.symmetrized(); // label 110
183 #ifdef DETAILED_REPORT
184  OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Printing projection matrix ar\n");
185  ar.printYourself();
186 #endif
187  //
188  for ( int j = 1; j <= nc; j++ ) {
189  tt.beColumnOf(r, j);
190 
191  b.times(tt, temp);
192  for ( int i = j; i <= nc; i++ ) {
193  brt = 0.;
194  for ( int k = 1; k <= nn; k++ ) {
195  brt += r.at(k, i) * temp.at(k);
196  }
197 
198  br.at(j, i) = brt;
199  } // label 180
200 
201  r.setColumn(temp, j); // (r=zbar)
202  } // label 160
203 
204  br.symmetrized();
205 #ifdef DETAILED_REPORT
206  OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Printing projection matrix br\n");
207  br.printYourself();
208 #endif
209 
210  //
211  // solution of reduced eigenvalue problem
212  //
213  mtd.solve(ar, br, eigv, vec);
214 
215  // START EXPERIMENTAL
216 #if 0
217  // solve the reduced problem by Inverse iteration
218  {
219  FloatMatrix x(nc,nc), z(nc,nc), zz(nc,nc), arinv;
220  FloatArray w(nc), ww(nc), tt(nc), t(nc);
221  double c;
222 
223  // initial setting
224  for ( int i = 1;i <= nc; i++ ) {
225  ww.at(i)=1.0;
226  }
227 
228 
229  for ( int i = 1;i <= nc; i++ )
230  for ( int j = 1; j <= nc;j++ )
231  z.at(i,j)=1.0;
232 
233  arinv.beInverseOf (ar);
234 
235  for ( int i = 0;i < nitem; i++ ) {
236  // copy zz=z
237  zz = z;
238 
239  // solve matrix equation K.X = M.X
240  x.beProductOf(arinv, z);
241  // evaluation of Rayleigh quotients
242  for ( int j = 1;j <= nc; j++ ) {
243  w.at(j) = 0.0;
244  for (k = 1; k<= nc; k++) w.at(j) += zz.at(k,j) * x.at(k,j);
245  }
246 
247  z.beProductOf (br, x);
248 
249  for ( int j = 1;j <= nc; j++ ) {
250  c = 0;
251  for ( int k = 1; k<= nc; k++ ) c += z.at(k,j) * x.at(k,j);
252  w.at(j) /= c;
253  }
254 
255  // check convergence
256  int ac = 0;
257  for ( int j = 1;j <= nc; j++ ) {
258  if (fabs((ww.at(j)-w.at(j))/w.at(j))< rtol) ac++;
259  ww.at(j) = w.at(j);
260  }
261 
262  //printf ("\n iterace cislo %d %d",i,ac);
263  //w.printYourself();
264 
265  // Gramm-Schmidt ortogonalization
266  for ( int j = 1;j <= nc;j++ ) {
267  for ( int k = 1; k<= nc; k++ ) tt.at(k) = x.at(k,j);
268  t.beProductOf(br,tt) ;
269  for ( int ii = 1;ii < j; ii++ ) {
270  c = 0.0;
271  for ( int k = 1; k<= nc; k++ ) c += x.at(k,ii) * t.at(k);
272  for ( int k = 1; k<= nc; k++ ) x.at(k,j) -= x.at(k,ii) * c;
273  }
274  for ( int k = 1; k<= nc; k++) tt.at(k) = x.at(k,j);
275  t.beProductOf(br, tt);
276  c = 0.0;
277  for ( int k = 1; k<= nc; k++) c += x.at(k,j)*t.at(k);
278  for ( int k = 1; k<= nc; k++) x.at(k,j) /= sqrt(c);
279  }
280 
281  if ( ac > nroot ) {
282  break;
283  }
284 
285  // compute new approximation of Z
286  z.beProductOf(br,x);
287  }
288 
289  eigv = w;
290  vec = x;
291  }
292 #endif
293 
294 
295  //
296  // sorting eigenvalues according to their values
297  //
298  do {
299  is = 0; // label 350
300  for ( int i = 1; i <= nc1; i++ ) {
301  if ( fabs( eigv.at(i + 1) ) < fabs( eigv.at(i) ) ) {
302  is++;
303  eigvt = eigv.at(i + 1);
304  eigv.at(i + 1) = eigv.at(i);
305  eigv.at(i) = eigvt;
306  for ( int k = 1; k <= nc; k++ ) {
307  rt = vec.at(k, i + 1);
308  vec.at(k, i + 1) = vec.at(k, i);
309  vec.at(k, i) = rt;
310  }
311  }
312  } // label 360
313  } while ( is != 0 );
314 
315 # ifdef DETAILED_REPORT
316  OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: current eigen values of reduced problem \n");
317  eigv.printYourself();
318  OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: current eigen vectors of reduced problem \n");
319  vec.printYourself();
320 # endif
321  //
322  // compute eigenvectors
323  //
324  for ( int i = 1; i <= nn; i++ ) { // label 375
325  for ( int j = 1; j <= nc; j++ ) {
326  tt.at(j) = r.at(i, j);
327  }
328 
329  for ( int k = 1; k <= nc; k++ ) {
330  rt = 0.;
331  for ( int j = 1; j <= nc; j++ ) {
332  rt += tt.at(j) * vec.at(j, k);
333  }
334 
335  r.at(i, k) = rt;
336  }
337  } // label 420 (r = z)
338 
339  //
340  // convergency check
341  //
342  for ( int i = 1; i <= nc; i++ ) {
343  double dif = ( eigv.at(i) - d.at(i) );
344  rtolv.at(i) = fabs( dif / eigv.at(i) );
345  }
346 
347 # ifdef DETAILED_REPORT
348  OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Reached precision of eigenvalues:\n");
349  rtolv.printYourself();
350 # endif
351  for ( int i = 1; i <= nroot; i++ ) {
352  if ( rtolv.at(i) > rtol ) {
353  goto label400;
354  }
355  }
356 
357  OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Convergence reached for RTOL=%20.15f\n", rtol);
358  break;
359 label400:
360  if ( nite >= nitem ) {
361  OOFEM_WARNING("SubspaceIteration :: solveYourselfAt: Convergence not reached in %d iteration - using current values", nitem);
362  break;
363  }
364 
365  d = eigv; // label 410 and 440
366 
367  continue;
368  }
369 
370 
371  // compute eigenvectors
372  for ( int j = 1; j <= nc; j++ ) {
373  tt.beColumnOf(r, j);
374 
375  a.backSubstitutionWith(tt);
376  r.setColumn(tt, j); // r = xbar
377  }
378 
379  // one cad add a normalization of eigen-vectors here
380 
381  // initialize original index locations
382  _r.resize(nn, nroot);
383  _eigv.resize(nroot);
384  for ( int i = 1; i <= nroot; i++ ) {
385  _eigv.at(i) = eigv.at(i);
386  for ( int j = 1; j <= nn; j++ ) {
387  _r.at(j, i) = r.at(j, i);
388  }
389  }
390 
391  return NM_Success;
392 }
393 } // end namespace oofem
#define NM_Success
Numerical method exited with success.
Definition: nmstatus.h:47
Class and object Domain.
Definition: domain.h:115
Base class for all matrices stored in sparse format.
Definition: sparsemtrx.h:60
virtual FloatArray * backSubstitutionWith(FloatArray &y) const
Computes the solution of linear system where A is receiver.
Definition: sparsemtrx.h:253
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
virtual NM_Status solve(SparseMtrx &A, SparseMtrx &B, FloatArray &x, FloatMatrix &v, double rtol, int nroot)
Solves the given sparse generalized eigen value system of equations .
Definition: subspaceit.C:61
virtual double & at(int i, int j)=0
Returns coefficient at position (i,j).
unsigned long NM_Status
Mask defining NumMetod Status; which can be asked after finishing computation by Numerical Method...
Definition: nmstatus.h:44
void beColumnOf(const FloatMatrix &mat, int col)
Reciever will be set to a given column in a matrix.
Definition: floatarray.C:1114
REGISTER_GeneralizedEigenValueSolver(InverseIteration, GES_InverseIt)
Domain * domain
Pointer to domain.
Definition: nummet.h:84
virtual ~SubspaceIteration()
Definition: subspaceit.C:57
#define OOFEM_LOG_INFO(...)
Definition: logger.h:127
#define OOFEM_ERROR(...)
Definition: error.h:61
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Receiver becomes the result of the product of aMatrix and anArray.
Definition: floatarray.C:676
ClassFactory & GiveClassFactory()
This function must be used by all code that run at link time to ensure that the classFactory is const...
Definition: classfactory.C:53
double at(int i, int j) const
Coefficient access function.
Definition: floatmatrix.h:176
This class implements the Generalized Jacobi Eigenvalue Problem Solver.
Definition: gjacobi.h:53
Class representing vector of real numbers.
Definition: floatarray.h:82
Implementation of matrix containing floating point numbers.
Definition: floatmatrix.h:94
SubspaceIteration(Domain *d, EngngModel *m)
Definition: subspaceit.C:50
void resize(int rows, int cols)
Checks size of receiver towards requested bounds.
Definition: floatmatrix.C:1358
virtual void printYourself() const
Print receiver on stdout.
Definition: floatarray.C:747
virtual SparseMtrx * factorized()
Returns the receiver factorized.
Definition: sparsemtrx.h:245
void zero()
Zeroes all coefficients of receiver.
Definition: floatarray.C:658
void setColumn(const FloatArray &src, int c)
Sets the values of the matrix in specified column.
Definition: floatmatrix.C:648
void printYourself() const
Prints matrix to stdout. Useful for debugging.
Definition: floatmatrix.C:1458
virtual NM_Status solve(FloatMatrix &K, FloatMatrix &M, FloatArray &w, FloatMatrix &x)
Solves the given sparse generalized eigenvalue system of equations .
Definition: gjacobi.C:55
void zero()
Zeroes all coefficient of receiver.
Definition: floatmatrix.C:1326
int giveNumberOfColumns() const
Returns number of columns of receiver.
Definition: sparsemtrx.h:116
int min(int i, int j)
Returns smaller value from two given decimals.
Definition: mathfem.h:59
Abstract base class representing the "problem" under consideration.
Definition: engngm.h:181
virtual void times(const FloatArray &x, FloatArray &answer) const
Evaluates .
Definition: sparsemtrx.h:137
the oofem namespace is to define a context or scope in which all oofem names are defined.
void beInverseOf(const FloatMatrix &src)
Modifies receiver to become inverse of given parameter.
Definition: floatmatrix.C:835
This base class is an abstraction for all numerical methods solving sparse linear system of equations...
void symmetrized()
Initializes the lower half of the receiver according to the upper half.
Definition: floatmatrix.C:1576
EngngModel * engngModel
Pointer to engineering model.
Definition: nummet.h:86
#define OOFEM_WARNING(...)
Definition: error.h:62
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:31 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011