Reference documentation for deal.II version 8.5.1
lapack_full_matrix.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2005 - 2017 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/lac/lapack_full_matrix.h>
18 #include <deal.II/lac/lapack_templates.h>
19 #include <deal.II/lac/lapack_support.h>
20 #include <deal.II/lac/full_matrix.h>
21 #include <deal.II/lac/sparse_matrix.h>
22 #include <deal.II/lac/vector.h>
23 #include <deal.II/lac/block_vector.h>
24 
25 #include <iostream>
26 #include <iomanip>
27 
28 DEAL_II_NAMESPACE_OPEN
29 
30 using namespace LAPACKSupport;
31 
32 template <typename number>
34  :
35  TransposeTable<number> (n,n),
36  state (matrix)
37 {}
38 
39 
40 template <typename number>
42  const size_type n)
43  :
44  TransposeTable<number> (m, n),
45  state (matrix)
46 {}
47 
48 
49 template <typename number>
51  :
52  TransposeTable<number> (M),
53  state (matrix)
54 {}
55 
56 
57 template <typename number>
60 {
62  state = LAPACKSupport::matrix;
63  return *this;
64 }
65 
66 
67 template <typename number>
68 void
70 {
71  this->TransposeTable<number>::reinit (n, n);
72  state = LAPACKSupport::matrix;
73 }
74 
75 
76 template <typename number>
77 void
79  const size_type n)
80 {
81  this->TransposeTable<number>::reinit (m, n);
82  state = LAPACKSupport::matrix;
83 }
84 
85 
86 template <typename number>
87 template <typename number2>
90 {
91  Assert (this->n_rows() == M.n_rows(), ExcDimensionMismatch(this->n_rows(), M.n_rows()));
92  Assert (this->n_cols() == M.n(), ExcDimensionMismatch(this->n_cols(), M.n()));
93  for (size_type i=0; i<this->n_rows(); ++i)
94  for (size_type j=0; j<this->n_cols(); ++j)
95  (*this)(i,j) = M(i,j);
96 
97  state = LAPACKSupport::matrix;
98  return *this;
99 }
100 
101 
102 template <typename number>
103 template <typename number2>
106 {
107  Assert (this->n_rows() == M.n(), ExcDimensionMismatch(this->n_rows(), M.n()));
108  Assert (this->n_cols() == M.m(), ExcDimensionMismatch(this->n_cols(), M.m()));
109  for (size_type i=0; i<this->n_rows(); ++i)
110  for (size_type j=0; j<this->n_cols(); ++j)
111  (*this)(i,j) = M.el(i,j);
112 
113  state = LAPACKSupport::matrix;
114  return *this;
115 }
116 
117 
118 template <typename number>
121 {
122  (void)d;
124 
125  if (this->n_elements() != 0)
126  this->reset_values();
127 
128  state = LAPACKSupport::matrix;
129  return *this;
130 }
131 
132 
133 template <typename number>
136 {
137  Assert(state == LAPACKSupport::matrix ||
138  state == LAPACKSupport::inverse_matrix,
139  ExcState(state));
140 
141  for (unsigned int column = 0; column<this->n(); ++column)
142  for (unsigned int row = 0; row<this->m(); ++row)
143  (*this)(row,column) *= factor;
144 
145  return *this;
146 }
147 
148 
149 template <typename number>
152 {
153  Assert(state == LAPACKSupport::matrix ||
154  state == LAPACKSupport::inverse_matrix,
155  ExcState(state));
156 
157  AssertIsFinite(factor);
158  Assert (factor != number(0.), ExcZero() );
159 
160  for (unsigned int column = 0; column<this->n(); ++column)
161  for (unsigned int row = 0; row<this->m(); ++row)
162  (*this)(row,column) /= factor;
163 
164  return *this;
165 }
166 
167 
168 template <typename number>
169 void
171  Vector<number> &w,
172  const Vector<number> &v,
173  const bool adding) const
174 {
175  const int mm = this->n_rows();
176  const int nn = this->n_cols();
177  const number alpha = 1.;
178  const number beta = (adding ? 1. : 0.);
179  const number null = 0.;
180 
181  switch (state)
182  {
183  case matrix:
184  case inverse_matrix:
185  {
186  AssertDimension(v.size(), this->n_cols());
187  AssertDimension(w.size(), this->n_rows());
188 
189  gemv("N", &mm, &nn, &alpha, &this->values[0], &mm, v.val, &one, &beta, w.val, &one);
190  break;
191  }
192  case svd:
193  {
194  AssertDimension(v.size(), this->n_cols());
195  AssertDimension(w.size(), this->n_rows());
196  // Compute V^T v
197  work.resize(std::max(mm,nn));
198  gemv("N", &nn, &nn, &alpha, &svd_vt->values[0], &nn, v.val, &one, &null, &work[0], &one);
199  // Multiply by singular values
200  for (size_type i=0; i<wr.size(); ++i)
201  work[i] *= wr[i];
202  // Multiply with U
203  gemv("N", &mm, &mm, &alpha, &svd_u->values[0], &mm, &work[0], &one, &beta, w.val, &one);
204  break;
205  }
206  case inverse_svd:
207  {
208  AssertDimension(w.size(), this->n_cols());
209  AssertDimension(v.size(), this->n_rows());
210  // Compute U^T v
211  work.resize(std::max(mm,nn));
212  gemv("T", &mm, &mm, &alpha, &svd_u->values[0], &mm, v.val, &one, &null, &work[0], &one);
213  // Multiply by singular values
214  for (size_type i=0; i<wr.size(); ++i)
215  work[i] *= wr[i];
216  // Multiply with V
217  gemv("T", &nn, &nn, &alpha, &svd_vt->values[0], &nn, &work[0], &one, &beta, w.val, &one);
218  break;
219  }
220  default:
221  Assert (false, ExcState(state));
222  }
223 }
224 
225 
226 template <typename number>
227 void
229  Vector<number> &w,
230  const Vector<number> &v,
231  const bool adding) const
232 {
233  const int mm = this->n_rows();
234  const int nn = this->n_cols();
235  const number alpha = 1.;
236  const number beta = (adding ? 1. : 0.);
237  const number null = 0.;
238 
239  switch (state)
240  {
241  case matrix:
242  case inverse_matrix:
243  {
244  AssertDimension(w.size(), this->n_cols());
245  AssertDimension(v.size(), this->n_rows());
246 
247  gemv("T", &mm, &nn, &alpha, &this->values[0], &mm, v.val, &one, &beta, w.val, &one);
248  break;
249  }
250  case svd:
251  {
252  AssertDimension(w.size(), this->n_cols());
253  AssertDimension(v.size(), this->n_rows());
254 
255  // Compute U^T v
256  work.resize(std::max(mm,nn));
257  gemv("T", &mm, &mm, &alpha, &svd_u->values[0], &mm, v.val, &one, &null, &work[0], &one);
258  // Multiply by singular values
259  for (size_type i=0; i<wr.size(); ++i)
260  work[i] *= wr[i];
261  // Multiply with V
262  gemv("T", &nn, &nn, &alpha, &svd_vt->values[0], &nn, &work[0], &one, &beta, w.val, &one);
263  break;
264  case inverse_svd:
265  {
266  AssertDimension(v.size(), this->n_cols());
267  AssertDimension(w.size(), this->n_rows());
268 
269  // Compute V^T v
270  work.resize(std::max(mm,nn));
271  gemv("N", &nn, &nn, &alpha, &svd_vt->values[0], &nn, v.val, &one, &null, &work[0], &one);
272  // Multiply by singular values
273  for (size_type i=0; i<wr.size(); ++i)
274  work[i] *= wr[i];
275  // Multiply with U
276  gemv("N", &mm, &mm, &alpha, &svd_u->values[0], &mm, &work[0], &one, &beta, w.val, &one);
277  break;
278  }
279  }
280  default:
281  Assert (false, ExcState(state));
282  }
283 }
284 
285 
286 template <typename number>
287 void
289  const Vector<number> &v) const
290 {
291  vmult(w, v, true);
292 }
293 
294 
295 template <typename number>
296 void
298  const Vector<number> &v) const
299 {
300  Tvmult(w, v, true);
301 }
302 
303 
304 template <typename number>
305 void
307  const LAPACKFullMatrix<number> &B,
308  const bool adding) const
309 {
310  Assert(state == matrix || state == inverse_matrix, ExcState(state));
311  Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
312  Assert(C.state == matrix || C.state == inverse_matrix, ExcState(state));
313  Assert (this->n_cols() == B.n_rows(), ExcDimensionMismatch(this->n_cols(), B.n_rows()));
314  Assert (C.n_cols() == B.n_cols(), ExcDimensionMismatch(C.n_cols(), B.n_cols()));
315  Assert (C.n_rows() == this->n_rows(), ExcDimensionMismatch(this->n_rows(), C.n_rows()));
316  const int mm = this->n_rows();
317  const int nn = B.n_cols();
318  const int kk = this->n_cols();
319  const number alpha = 1.;
320  const number beta = (adding ? 1. : 0.);
321 
322  gemm("N", "N", &mm, &nn, &kk, &alpha, &this->values[0], &mm, &B.values[0],
323  &kk, &beta, &C.values[0], &mm);
324 }
325 
326 
327 template <typename number>
328 void
330  const LAPACKFullMatrix<number> &B,
331  const bool adding) const
332 {
333  Assert(state == matrix || state == inverse_matrix, ExcState(state));
334  Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
335  Assert (this->n_cols() == B.n_rows(), ExcDimensionMismatch(this->n_cols(), B.n_rows()));
336  Assert (C.n_cols() == B.n_cols(), ExcDimensionMismatch(C.n_cols(), B.n_cols()));
337  Assert (C.n_rows() == this->n_rows(), ExcDimensionMismatch(this->n_rows(), C.n_rows()));
338  const int mm = this->n_rows();
339  const int nn = B.n_cols();
340  const int kk = this->n_cols();
341  const number alpha = 1.;
342  const number beta = (adding ? 1. : 0.);
343 
344  // since FullMatrix stores the matrix in transposed order compared to this
345  // matrix, compute B^T * A^T = (A * B)^T
346  gemm("T", "T", &nn, &mm, &kk, &alpha, &B.values[0], &kk, &this->values[0],
347  &mm, &beta, &C(0,0), &nn);
348 }
349 
350 
351 
352 template <typename number>
353 void
355  const LAPACKFullMatrix<number> &B,
356  const bool adding) const
357 {
358  Assert(state == matrix || state == inverse_matrix, ExcState(state));
359  Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
360  Assert(C.state == matrix || C.state == inverse_matrix, ExcState(state));
361  Assert (this->n_rows() == B.n_rows(), ExcDimensionMismatch(this->n_rows(), B.n_rows()));
362  Assert (C.n_cols() == B.n_cols(), ExcDimensionMismatch(C.n_cols(), B.n_cols()));
363  Assert (C.n_rows() == this->n_cols(), ExcDimensionMismatch(this->n_cols(), C.n_rows()));
364  const int mm = this->n_cols();
365  const int nn = B.n_cols();
366  const int kk = B.n_rows();
367  const number alpha = 1.;
368  const number beta = (adding ? 1. : 0.);
369 
370  gemm("T", "N", &mm, &nn, &kk, &alpha, &this->values[0], &kk, &B.values[0],
371  &kk, &beta, &C.values[0], &mm);
372 }
373 
374 
375 template <typename number>
376 void
378  const LAPACKFullMatrix<number> &B,
379  const bool adding) const
380 {
381  Assert(state == matrix || state == inverse_matrix, ExcState(state));
382  Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
383  Assert (this->n_rows() == B.n_rows(), ExcDimensionMismatch(this->n_rows(), B.n_rows()));
384  Assert (C.n_cols() == B.n_cols(), ExcDimensionMismatch(C.n_cols(), B.n_cols()));
385  Assert (C.n_rows() == this->n_cols(), ExcDimensionMismatch(this->n_cols(), C.n_rows()));
386  const int mm = this->n_cols();
387  const int nn = B.n_cols();
388  const int kk = B.n_rows();
389  const number alpha = 1.;
390  const number beta = (adding ? 1. : 0.);
391 
392  // since FullMatrix stores the matrix in transposed order compared to this
393  // matrix, compute B^T * A = (A^T * B)^T
394  gemm("T", "N", &nn, &mm, &kk, &alpha, &B.values[0], &kk, &this->values[0],
395  &kk, &beta, &C(0,0), &nn);
396 }
397 
398 
399 template <typename number>
400 void
402  const LAPACKFullMatrix<number> &B,
403  const bool adding) const
404 {
405  Assert(state == matrix || state == inverse_matrix, ExcState(state));
406  Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
407  Assert(C.state == matrix || C.state == inverse_matrix, ExcState(state));
408  Assert (this->n_cols() == B.n_cols(), ExcDimensionMismatch(this->n_cols(), B.n_cols()));
409  Assert (C.n_cols() == B.n_rows(), ExcDimensionMismatch(C.n_cols(), B.n_rows()));
410  Assert (C.n_rows() == this->n_rows(), ExcDimensionMismatch(this->n_rows(), C.n_rows()));
411  const int mm = this->n_rows();
412  const int nn = B.n_rows();
413  const int kk = B.n_cols();
414  const number alpha = 1.;
415  const number beta = (adding ? 1. : 0.);
416 
417  gemm("N", "T", &mm, &nn, &kk, &alpha, &this->values[0], &mm, &B.values[0],
418  &nn, &beta, &C.values[0], &mm);
419 }
420 
421 
422 
423 template <typename number>
424 void
426  const LAPACKFullMatrix<number> &B,
427  const bool adding) const
428 {
429  Assert(state == matrix || state == inverse_matrix, ExcState(state));
430  Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
431  Assert (this->n_cols() == B.n_cols(), ExcDimensionMismatch(this->n_cols(), B.n_cols()));
432  Assert (C.n_cols() == B.n_rows(), ExcDimensionMismatch(C.n_cols(), B.n_rows()));
433  Assert (C.n_rows() == this->n_rows(), ExcDimensionMismatch(this->n_rows(), C.n_rows()));
434  const int mm = this->n_rows();
435  const int nn = B.n_rows();
436  const int kk = B.n_cols();
437  const number alpha = 1.;
438  const number beta = (adding ? 1. : 0.);
439 
440  // since FullMatrix stores the matrix in transposed order compared to this
441  // matrix, compute B * A^T = (A * B^T)^T
442  gemm("N", "T", &nn, &mm, &kk, &alpha, &B.values[0], &nn, &this->values[0],
443  &mm, &beta, &C(0,0), &nn);
444 }
445 
446 
447 template <typename number>
448 void
450  const LAPACKFullMatrix<number> &B,
451  const bool adding) const
452 {
453  Assert(state == matrix || state == inverse_matrix, ExcState(state));
454  Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
455  Assert(C.state == matrix || C.state == inverse_matrix, ExcState(state));
456  Assert (this->n_rows() == B.n_cols(), ExcDimensionMismatch(this->n_rows(), B.n_cols()));
457  Assert (C.n_cols() == B.n_rows(), ExcDimensionMismatch(C.n_cols(), B.n_rows()));
458  Assert (C.n_rows() == this->n_cols(), ExcDimensionMismatch(this->n_cols(), C.n_rows()));
459  const int mm = this->n_cols();
460  const int nn = B.n_rows();
461  const int kk = B.n_cols();
462  const number alpha = 1.;
463  const number beta = (adding ? 1. : 0.);
464 
465  gemm("T", "T", &mm, &nn, &kk, &alpha, &this->values[0], &kk, &B.values[0],
466  &nn, &beta, &C.values[0], &mm);
467 }
468 
469 
470 template <typename number>
471 void
473  const LAPACKFullMatrix<number> &B,
474  const bool adding) const
475 {
476  Assert(state == matrix || state == inverse_matrix, ExcState(state));
477  Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
478  Assert (this->n_rows() == B.n_cols(), ExcDimensionMismatch(this->n_rows(), B.n_cols()));
479  Assert (C.n_cols() == B.n_rows(), ExcDimensionMismatch(C.n_cols(), B.n_rows()));
480  Assert (C.n_rows() == this->n_cols(), ExcDimensionMismatch(this->n_cols(), C.n_rows()));
481  const int mm = this->n_cols();
482  const int nn = B.n_rows();
483  const int kk = B.n_cols();
484  const number alpha = 1.;
485  const number beta = (adding ? 1. : 0.);
486 
487  // since FullMatrix stores the matrix in transposed order compared to this
488  // matrix, compute B * A = (A^T * B^T)^T
489  gemm("N", "N", &nn, &mm, &kk, &alpha, &B.values[0], &nn, &this->values[0],
490  &kk, &beta, &C(0,0), &nn);
491 }
492 
493 
494 template <typename number>
495 void
497 {
498  Assert(state == matrix, ExcState(state));
499  state = LAPACKSupport::unusable;
500 
501  const int mm = this->n_rows();
502  const int nn = this->n_cols();
503  number *values = const_cast<number *> (&this->values[0]);
504  ipiv.resize(mm);
505  int info = 0;
506  getrf(&mm, &nn, values, &mm, &ipiv[0], &info);
507 
508  Assert(info >= 0, ExcInternalError());
509 
510  // if info >= 0, the factorization has been completed
511  state = lu;
512 
514 }
515 
516 
517 template <typename number>
518 void
520 {
521  Assert(state == matrix, ExcState(state));
522  state = LAPACKSupport::unusable;
523 
524  const int mm = this->n_rows();
525  const int nn = this->n_cols();
526  number *values = const_cast<number *> (&this->values[0]);
527  wr.resize(std::max(mm,nn));
528  std::fill(wr.begin(), wr.end(), 0.);
529  ipiv.resize(8*mm);
530 
531  svd_u.reset (new LAPACKFullMatrix<number>(mm,mm));
532  svd_vt.reset (new LAPACKFullMatrix<number>(nn,nn));
533  number *mu = const_cast<number *> (&svd_u->values[0]);
534  number *mvt = const_cast<number *> (&svd_vt->values[0]);
535  int info = 0;
536 
537  // First determine optimal workspace size
538  work.resize(1);
539  int lwork = -1;
540  gesdd(&LAPACKSupport::A, &mm, &nn, values, &mm,
541  &wr[0], mu, &mm, mvt, &nn,
542  &work[0], &lwork, &ipiv[0], &info);
543  AssertThrow (info==0, LAPACKSupport::ExcErrorCode("gesdd", info));
544  // Resize the work array. Add one to the size computed by LAPACK to be on
545  // the safe side.
546  lwork = static_cast<int>(work[0] + 1);
547 
548  work.resize(lwork);
549  // Do the actual SVD.
550  gesdd(&LAPACKSupport::A, &mm, &nn, values, &mm,
551  &wr[0], mu, &mm, mvt, &nn,
552  &work[0], &lwork, &ipiv[0], &info);
553  AssertThrow (info==0, LAPACKSupport::ExcErrorCode("gesdd", info));
554 
555  work.resize(0);
556  ipiv.resize(0);
557 
558  state = LAPACKSupport::svd;
559 }
560 
561 
562 template <typename number>
563 void
565 {
566  if (state == LAPACKSupport::matrix)
567  compute_svd();
568 
569  Assert (state==LAPACKSupport::svd, ExcState(state));
570 
571  const double lim = wr[0]*threshold;
572  for (size_type i=0; i<wr.size(); ++i)
573  {
574  if (wr[i] > lim)
575  wr[i] = 1./wr[i];
576  else
577  wr[i] = 0.;
578  }
579  state = LAPACKSupport::inverse_svd;
580 }
581 
582 
583 template <typename number>
584 void
586 {
587  Assert(state == matrix || state == lu,
588  ExcState(state));
589  const int mm = this->n_rows();
590  const int nn = this->n_cols();
591  Assert (nn == mm, ExcNotQuadratic());
592 
593  number *values = const_cast<number *> (&this->values[0]);
594  ipiv.resize(mm);
595  int info = 0;
596 
597  if (state == matrix)
598  {
599  getrf(&mm, &nn, values, &mm, &ipiv[0], &info);
600 
601  Assert(info >= 0, ExcInternalError());
603  }
604 
605  inv_work.resize (mm);
606  getri(&mm, values, &mm, &ipiv[0], &inv_work[0], &mm, &info);
607 
608  Assert(info >= 0, ExcInternalError());
610 
611  state = inverse_matrix;
612 }
613 
614 
615 template <typename number>
616 void
618  const bool transposed) const
619 {
620  Assert(state == lu, ExcState(state));
621  Assert(this->n_rows() == this->n_cols(),
623  AssertDimension(this->n_rows(), v.size());
624 
625  const char *trans = transposed ? &T : &N;
626  const int nn = this->n_cols();
627  const number *values = &this->values[0];
628  int info = 0;
629 
630  getrs(trans, &nn, &one, values, &nn, &ipiv[0],
631  v.begin(), &nn, &info);
632 
633  Assert(info == 0, ExcInternalError());
634 }
635 
636 
637 template <typename number>
638 void
640  const bool transposed) const
641 {
642  Assert(state == lu, ExcState(state));
643  Assert(B.state == matrix, ExcState(state));
644  Assert(this->n_rows() == this->n_cols(), LACExceptions::ExcNotQuadratic());
645  AssertDimension(this->n_rows(), B.n_rows());
646 
647  const char *trans = transposed ? &T : &N;
648  const int nn = this->n_cols();
649  const int kk = B.n_cols();
650  const number *values = &this->values[0];
651  int info = 0;
652 
653  getrs(trans, &nn, &kk, values, &nn, &ipiv[0], &B.values[0], &nn, &info);
654 
655  Assert(info == 0, ExcInternalError());
656 }
657 
658 
659 template <typename number>
660 void
662  const bool left)
663 {
664  Assert(state == matrix, ExcState(state));
665  const int nn = this->n_cols();
666  wr.resize(nn);
667  wi.resize(nn);
668  if (right) vr.resize(nn*nn);
669  if (left) vl.resize(nn*nn);
670 
671  number *values = const_cast<number *> (&this->values[0]);
672 
673  int info = 0;
674  int lwork = 1;
675  const char *const jobvr = (right) ? (&V) : (&N);
676  const char *const jobvl = (left) ? (&V) : (&N);
677 
678  /*
679  * The LAPACK routine xGEEV requires a sufficiently large work array; the
680  * minimum requirement is
681  *
682  * work.size >= 4*nn.
683  *
684  * However, for better performance, a larger work array may be needed. The
685  * first call determines the optimal work size and the second does the work.
686  */
687  lwork = -1;
688  work.resize(1);
689 
690  geev(jobvl, jobvr, &nn, values, &nn,
691  &wr[0], &wi[0],
692  &vl[0], &nn, &vr[0], &nn,
693  &work[0], &lwork, &info);
694  // geev returns info=0 on success. Since we only queried the optimal size
695  // for work, everything else would not be acceptable.
696  Assert (info == 0, ExcInternalError());
697  // Allocate working array according to suggestion (same strategy as was
698  // noted in compute_svd).
699  lwork = static_cast<int>(work[0] + 1);
700 
701  // resize workspace array
702  work.resize((size_type ) lwork);
703 
704  // Finally compute the eigenvalues.
705  geev(jobvl, jobvr, &nn, values, &nn,
706  &wr[0], &wi[0],
707  &vl[0], &nn, &vr[0], &nn,
708  &work[0], &lwork, &info);
709  // Negative return value implies a wrong argument. This should be internal.
710 
711  Assert (info >=0, ExcInternalError());
712 //TODO:[GK] What if the QR method fails?
713  if (info != 0)
714  std::cerr << "LAPACK error in geev" << std::endl;
715 
716  state = LAPACKSupport::State(eigenvalues | unusable);
717 }
718 
719 
720 template <typename number>
721 void
723  const number upper_bound,
724  const number abs_accuracy,
725  Vector<number> &eigenvalues,
726  FullMatrix<number> &eigenvectors)
727 {
728  Assert(state == matrix, ExcState(state));
729  const int nn = (this->n_cols() > 0 ? this->n_cols() : 1);
730  Assert(static_cast<size_type>(nn) == this->n_rows(), ExcNotQuadratic());
731 
732  wr.resize(nn);
733  LAPACKFullMatrix<number> matrix_eigenvectors(nn, nn);
734 
735  number *values_A = const_cast<number *> (&this->values[0]);
736  number *values_eigenvectors = const_cast<number *> (&matrix_eigenvectors.values[0]);
737 
738  int info(0),
739  lwork(-1),
740  n_eigenpairs(0);
741  const char *const jobz(&V);
742  const char *const uplo(&U);
743  const char *const range(&V);
744  const int *const dummy(&one);
745  std::vector<int> iwork(static_cast<size_type> (5*nn));
746  std::vector<int> ifail(static_cast<size_type> (nn));
747 
748 
749  /*
750  * The LAPACK routine xSYEVX requires a sufficiently large work array; the
751  * minimum requirement is
752  *
753  * work.size >= 8*nn.
754  *
755  * However, for better performance, a larger work array may be needed. The
756  * first call determines the optimal work size and the second does the work.
757  */
758  work.resize(1);
759 
760  syevx (jobz, range,
761  uplo, &nn, values_A, &nn,
762  &lower_bound, &upper_bound,
763  dummy, dummy, &abs_accuracy,
764  &n_eigenpairs, &wr[0], values_eigenvectors,
765  &nn, &work[0], &lwork, &iwork[0],
766  &ifail[0], &info);
767  // syevx returns info=0 on success. Since we only queried the optimal size
768  // for work, everything else would not be acceptable.
769  Assert (info == 0, ExcInternalError());
770  // Allocate working array according to suggestion (same strategy as was noted in
771  // compute_svd).
772  lwork = static_cast<int>(work[0] + 1);
773  work.resize(static_cast<size_type> (lwork));
774 
775  // Finally compute the eigenvalues.
776  syevx (jobz, range,
777  uplo, &nn, values_A, &nn,
778  &lower_bound, &upper_bound,
779  dummy, dummy, &abs_accuracy,
780  &n_eigenpairs, &wr[0], values_eigenvectors,
781  &nn, &work[0], &lwork, &iwork[0],
782  &ifail[0], &info);
783 
784  // Negative return value implies a wrong argument. This should be internal.
785  Assert (info >=0, ExcInternalError());
786  if (info != 0)
787  std::cerr << "LAPACK error in syevx" << std::endl;
788 
789  eigenvalues.reinit(n_eigenpairs);
790  eigenvectors.reinit(nn, n_eigenpairs, true);
791 
792  for (size_type i=0; i < static_cast<size_type> (n_eigenpairs); ++i)
793  {
794  eigenvalues(i) = wr[i];
795  size_type col_begin(i*nn);
796  for (size_type j=0; j < static_cast<size_type> (nn); ++j)
797  {
798  eigenvectors(j,i) = values_eigenvectors[col_begin+j];
799  }
800  }
801 
802  state = LAPACKSupport::State(unusable);
803 }
804 
805 
806 template <typename number>
807 void
810  const number lower_bound,
811  const number upper_bound,
812  const number abs_accuracy,
813  Vector<number> &eigenvalues,
814  std::vector<Vector<number> > &eigenvectors,
815  const int itype)
816 {
817  Assert(state == matrix, ExcState(state));
818  const int nn = (this->n_cols() > 0 ? this->n_cols() : 1);
819  Assert(static_cast<size_type>(nn) == this->n_rows(), ExcNotQuadratic());
820  Assert(B.n_rows() == B.n_cols(), ExcNotQuadratic());
821  Assert(static_cast<size_type>(nn) == B.n_cols(),
822  ExcDimensionMismatch (nn, B.n_cols()));
823 
824  wr.resize(nn);
825  LAPACKFullMatrix<number> matrix_eigenvectors(nn, nn);
826 
827  number *values_A = const_cast<number *> (&this->values[0]);
828  number *values_B = const_cast<number *> (&B.values[0]);
829  number *values_eigenvectors = const_cast<number *> (&matrix_eigenvectors.values[0]);
830 
831  int info(0),
832  lwork(-1),
833  n_eigenpairs(0);
834  const char *const jobz(&V);
835  const char *const uplo(&U);
836  const char *const range(&V);
837  const int *const dummy(&one);
838  std::vector<int> iwork(static_cast<size_type> (5*nn));
839  std::vector<int> ifail(static_cast<size_type> (nn));
840 
841 
842  /*
843  * The LAPACK routine xSYGVX requires a sufficiently large work array; the
844  * minimum requirement is
845  *
846  * work.size >= 8*nn.
847  *
848  * However, for better performance, a larger work array may be needed. The
849  * first call determines the optimal work size and the second does the work.
850  */
851  work.resize(1);
852 
853  sygvx (&itype, jobz, range, uplo, &nn, values_A, &nn,
854  values_B, &nn, &lower_bound, &upper_bound,
855  dummy, dummy, &abs_accuracy, &n_eigenpairs,
856  &wr[0], values_eigenvectors, &nn, &work[0],
857  &lwork, &iwork[0], &ifail[0], &info);
858  // sygvx returns info=0 on success. Since we only queried the optimal size
859  // for work, everything else would not be acceptable.
860  Assert (info == 0, ExcInternalError());
861  // Allocate working array according to suggestion (same strategy as was
862  // noted in compute_svd).
863  lwork = static_cast<int>(work[0] + 1);
864 
865  // resize workspace arrays
866  work.resize(static_cast<size_type> (lwork));
867 
868  // Finally compute the generalized eigenvalues.
869  sygvx (&itype, jobz, range, uplo, &nn, values_A, &nn,
870  values_B, &nn, &lower_bound, &upper_bound,
871  dummy, dummy, &abs_accuracy, &n_eigenpairs,
872  &wr[0], values_eigenvectors, &nn, &work[0],
873  &lwork, &iwork[0], &ifail[0], &info);
874 
875  // Negative return value implies a wrong argument. This should be internal.
876  Assert (info >=0, ExcInternalError());
877  if (info != 0)
878  std::cerr << "LAPACK error in sygvx" << std::endl;
879 
880  eigenvalues.reinit(n_eigenpairs);
881  eigenvectors.resize(n_eigenpairs);
882 
883  for (size_type i=0; i < static_cast<size_type> (n_eigenpairs); ++i)
884  {
885  eigenvalues(i) = wr[i];
886  size_type col_begin(i*nn);
887  eigenvectors[i].reinit(nn, true);
888  for (size_type j=0; j < static_cast<size_type> (nn); ++j)
889  {
890  eigenvectors[i](j) = values_eigenvectors[col_begin+j];
891  }
892  }
893 
894  state = LAPACKSupport::State(unusable);
895 }
896 
897 
898 template <typename number>
899 void
902  std::vector<Vector<number> > &eigenvectors,
903  const int itype)
904 {
905  Assert(state == matrix, ExcState(state));
906  const int nn = this->n_cols();
907  Assert(static_cast<size_type>(nn) == this->n_rows(), ExcNotQuadratic());
908  Assert(B.n_rows() == B.n_cols(), ExcNotQuadratic());
909  Assert(static_cast<size_type>(nn) == B.n_cols(),
910  ExcDimensionMismatch (nn, B.n_cols()));
911  Assert(eigenvectors.size() <= static_cast<size_type>(nn),
912  ExcMessage ("eigenvectors.size() > matrix.n_cols()"));
913 
914  wr.resize(nn);
915  wi.resize(nn); //This is set purely for consistency reasons with the
916  //eigenvalues() function.
917 
918  number *values_A = const_cast<number *> (&this->values[0]);
919  number *values_B = const_cast<number *> (&B.values[0]);
920 
921  int info = 0;
922  int lwork = -1;
923  const char *const jobz = (eigenvectors.size() > 0) ? (&V) : (&N);
924  const char *const uplo = (&U);
925 
926  /*
927  * The LAPACK routine xSYGV requires a sufficiently large work array; the
928  * minimum requirement is
929  *
930  * work.size >= 3*nn - 1.
931  *
932  * However, for better performance, a larger work array may be needed. The
933  * first call determines the optimal work size and the second does the work.
934  */
935  work.resize(1);
936 
937  sygv (&itype, jobz, uplo, &nn, values_A, &nn,
938  values_B, &nn,
939  &wr[0], &work[0], &lwork, &info);
940  // sygv returns info=0 on success. Since we only queried the optimal size
941  // for work, everything else would not be acceptable.
942  Assert (info == 0, ExcInternalError());
943  // Allocate working array according to suggestion (same strategy as was
944  // noted in compute_svd).
945  lwork = static_cast<int>(work[0] + 1);
946 
947  // resize workspace array
948  work.resize(static_cast<size_type>(lwork));
949 
950  // Finally compute the generalized eigenvalues.
951  sygv (&itype, jobz, uplo, &nn, values_A, &nn,
952  values_B, &nn,
953  &wr[0], &work[0], &lwork, &info);
954  // Negative return value implies a wrong argument. This should be internal.
955 
956  Assert (info >=0, ExcInternalError());
957  if (info != 0)
958  std::cerr << "LAPACK error in sygv" << std::endl;
959 
960  for (size_type i=0; i < eigenvectors.size(); ++i)
961  {
962  size_type col_begin(i*nn);
963  eigenvectors[i].reinit(nn, true);
964  for (size_type j=0; j < static_cast<size_type>(nn); ++j)
965  {
966  eigenvectors[i](j) = values_A[col_begin+j];
967  }
968  }
969  state = LAPACKSupport::State(eigenvalues | unusable);
970 }
971 
972 
973 template <typename number>
974 void
976  std::ostream &out,
977  const unsigned int precision,
978  const bool scientific,
979  const unsigned int width_,
980  const char *zero_string,
981  const double denominator,
982  const double threshold) const
983 {
984  unsigned int width = width_;
985 
986  Assert ((!this->empty()) || (this->n_cols()+this->n_rows()==0),
987  ExcInternalError());
988  Assert (state == LAPACKSupport::matrix ||
989  state == LAPACKSupport::inverse_matrix,
990  ExcState(state));
991 
992  // set output format, but store old
993  // state
994  std::ios::fmtflags old_flags = out.flags();
995  unsigned int old_precision = out.precision (precision);
996 
997  if (scientific)
998  {
999  out.setf (std::ios::scientific, std::ios::floatfield);
1000  if (!width)
1001  width = precision+7;
1002  }
1003  else
1004  {
1005  out.setf (std::ios::fixed, std::ios::floatfield);
1006  if (!width)
1007  width = precision+2;
1008  }
1009 
1010  for (size_type i=0; i<this->n_rows(); ++i)
1011  {
1012  for (size_type j=0; j<this->n_cols(); ++j)
1013  if (std::fabs(this->el(i,j)) > threshold)
1014  out << std::setw(width)
1015  << this->el(i,j) * denominator << ' ';
1016  else
1017  out << std::setw(width) << zero_string << ' ';
1018  out << std::endl;
1019  };
1020 
1021  AssertThrow (out, ExcIO());
1022  // reset output format
1023  out.flags (old_flags);
1024  out.precision(old_precision);
1025 }
1026 
1027 
1028 //----------------------------------------------------------------------//
1029 
1030 template <typename number>
1031 void
1033 {
1034  matrix = &M;
1035  mem = 0;
1036 }
1037 
1038 
1039 template <typename number>
1040 void
1043 {
1044  matrix = &M;
1045  mem = &V;
1046 }
1047 
1048 
1049 template <typename number>
1050 void
1052  const Vector<number> &src) const
1053 {
1054  dst = src;
1055  matrix->apply_lu_factorization(dst, false);
1056 }
1057 
1058 
1059 template <typename number>
1060 void
1062  const Vector<number> &src) const
1063 {
1064  dst = src;
1065  matrix->apply_lu_factorization(dst, true);
1066 }
1067 
1068 
1069 template <typename number>
1070 void
1072  const BlockVector<number> &src) const
1073 {
1074  Assert(mem != 0, ExcNotInitialized());
1075  Vector<number> *aux = mem->alloc();
1076  *aux = src;
1077  matrix->apply_lu_factorization(*aux, false);
1078  dst = *aux;
1079 }
1080 
1081 
1082 template <typename number>
1083 void
1085  const BlockVector<number> &src) const
1086 {
1087  Assert(mem != 0, ExcNotInitialized());
1088  Vector<number> *aux = mem->alloc();
1089  *aux = src;
1090  matrix->apply_lu_factorization(*aux, true);
1091  dst = *aux;
1092 }
1093 
1094 
1095 
1096 #include "lapack_full_matrix.inst"
1097 
1098 
1099 DEAL_II_NAMESPACE_CLOSE
LAPACKFullMatrix(const size_type size=0)
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1146
void TmTmult(LAPACKFullMatrix< number > &C, const LAPACKFullMatrix< number > &B, const bool adding=false) const
LAPACKFullMatrix< number > & operator/=(const number factor)
void Tvmult(Vector< number2 > &w, const Vector< number2 > &v, const bool adding=false) const
static ::ExceptionBase & ExcIO()
LAPACKSupport::State state
static ::ExceptionBase & ExcScalarAssignmentOnlyForZeroValue()
TableBase< N, T > & operator=(const TableBase< N, T > &src)
static ::ExceptionBase & ExcNotInitialized()
#define AssertThrow(cond, exc)
Definition: exceptions.h:369
void compute_eigenvalues_symmetric(const number lower_bound, const number upper_bound, const number abs_accuracy, Vector< number > &eigenvalues, FullMatrix< number > &eigenvectors)
unsigned int n_cols() const
void reinit(const size_type size)
void Tmmult(LAPACKFullMatrix< number > &C, const LAPACKFullMatrix< number > &B, const bool adding=false) const
static ::ExceptionBase & ExcSingular()
size_type n() const
static ::ExceptionBase & ExcState(State arg1)
static ::ExceptionBase & ExcMessage(std::string arg1)
void mTmult(LAPACKFullMatrix< number > &C, const LAPACKFullMatrix< number > &B, const bool adding=false) const
TableBase< 2, T >::size_type size_type
Definition: table.h:1530
size_type n() const
void reinit(const TableIndices< N > &new_size, const bool omit_default_initialization=false)
#define Assert(cond, exc)
Definition: exceptions.h:313
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
std::size_t size() const
unsigned int n_rows() const
static ::ExceptionBase & ExcErrorCode(char *arg1, int arg2)
iterator begin()
void vmult(Vector< number2 > &w, const Vector< number2 > &v, const bool adding=false) const
void compute_generalized_eigenvalues_symmetric(LAPACKFullMatrix< number > &B, const number lower_bound, const number upper_bound, const number abs_accuracy, Vector< number > &eigenvalues, std::vector< Vector< number > > &eigenvectors, const int itype=1)
void print_formatted(std::ostream &out, const unsigned int precision=3, const bool scientific=true, const unsigned int width=0, const char *zero_string=" ", const double denominator=1., const double threshold=0.) const
LAPACKFullMatrix< number > & operator*=(const number factor)
void compute_inverse_svd(const double threshold=0.)
static ::ExceptionBase & ExcNotQuadratic()
LAPACKFullMatrix< number > & operator=(const LAPACKFullMatrix< number > &)
number el(const size_type i, const size_type j) const
void Tvmult_add(Vector< number2 > &w, const Vector< number2 > &v) const
size_type m() const
void compute_eigenvalues(const bool right_eigenvectors=false, const bool left_eigenvectors=false)
void apply_lu_factorization(Vector< number > &v, const bool transposed) const
Number * val
Definition: vector.h:1018
AlignedVector< number > values
Definition: table.h:654
void reinit(const unsigned int size1, const unsigned int size2, const bool omit_default_initialization=false)
static ::ExceptionBase & ExcZero()
#define AssertIsFinite(number)
Definition: exceptions.h:1197
void vmult_add(Vector< number2 > &w, const Vector< number2 > &v) const
void mmult(LAPACKFullMatrix< number > &C, const LAPACKFullMatrix< number > &B, const bool adding=false) const
static ::ExceptionBase & ExcInternalError()