NeoPZ
pzsespmat.cpp
Go to the documentation of this file.
1 
6 #include <math.h>
7 #include <stdlib.h>
8 
9 #include "pzfmatrix.h"
10 #include "pzsespmat.h"
11 //#include "pzerror.h"
12 
13 #include <sstream>
14 #include "pzlog.h"
15 #ifdef LOG4CXX
16 static LoggerPtr logger(Logger::getLogger("pz.matrix.tpzsspmatrix"));
17 #endif
18 
19 using namespace std;
20 
21 /*******************/
22 /*** TPZSSpMatrix ***/
23 
24 /**************************** PUBLIC ****************************/
25 
26 /*******************/
27 /*** Constructor ***/
28 
29 template<class TVar>
31 : TPZMatrix<TVar>( A ), fMat( A.fMat )
32 {
33 
34  this->fDecomposed = A.fDecomposed;
35  this->fDefPositive = A.fDefPositive;
36 }
37 
38 /******** Operacoes com matrizes ESPARSAS SIMETRICAS ********/
39 
40 /******************/
41 /*** Operator = ***/
42 
43 template<class TVar>
46 {
47  fMat = A.fMat;
48  this->fRow = this->fCol = A.Dim();
49  this->fDecomposed = A.fDecomposed;
50  this->fDefPositive = A.fDefPositive;
51  return( *this );
52 }
53 
54 
55 
56 /******************/
57 /*** Operator + ***/
58 
59 template<class TVar>
62 {
63  if ( this->Dim() != A.Dim() )
64  TPZMatrix<TVar>::Error(__PRETTY_FUNCTION__, "Operator+ (TPZSSpMatrix&) <incompatible dimensions>" );
65  TPZSSpMatrix res( *this );
66  res.fMat.fAdd( &A.fMat );
67  return( res );
68 }
69 
70 
71 
72 /******************/
73 /*** Operator - ***/
74 
75 template<class TVar>
78 {
79  if ( this->Dim() != A.Dim() )
80  TPZMatrix<TVar>::Error(__PRETTY_FUNCTION__, "Operator-( TPZSSpMatrix& ) <incompatible dimensions>" );
81 
82  TPZSSpMatrix res( *this );
83  res.fMat.fSub( &A.fMat );
84  return( res );
85 }
86 
87 
88 
89 /*******************/
90 /*** Operator += ***/
91 
92 template<class TVar>
95 {
96  if ( this->Dim() != A.Dim() )
97  TPZMatrix<TVar>::Error(__PRETTY_FUNCTION__, "operator+( TPZSSpMatrix ) <incompatible dimensions>" );
98 
99  fMat.fAdd( &A.fMat );
100  this->fDecomposed = 0;
101  return( *this );
102 }
103 
104 
105 
106 /*******************/
107 /*** Operator -= ***/
108 
109 template<class TVar>
112 {
113  if ( this->Dim() != A.Dim() )
114  TPZMatrix<TVar>::Error(__PRETTY_FUNCTION__, "operator+( TPZSSpMatrix ) <incompatible dimensions>" );
115 
116  fMat.fSub( &A.fMat );
117  this->fDecomposed = 0;
118  return( *this );
119 }
120 
121 
122 
123 /******** Operacoes com matrizes GENERICAS ********/
124 
125 // Estas operacoes com matrizes genericas, usam a parte triangular
126 // inferior da maior matriz quadrada de A. Ex.:
127 //
128 // Se A = 01 02 03 04 A matriz usada sera': 01 05 09
129 // 05 06 07 08 05 06 10
130 // 09 10 11 12 09 10 11
131 //
132 
133 
134 
135 /******** Operacoes com valores NUMERICOS ********/
136 
137 
138 
139 /*****************************/
140 /*** Operator * ( REAL ) ***/
141 
142 template<class TVar>
144 TPZSSpMatrix<TVar>::operator*(const TVar value ) const
145 {
146  TPZSSpMatrix<TVar> res( *this );
147  res.fMat.fMult( value );
148  return( res );
149 }
150 
151 
152 
153 
154 /******************************/
155 /*** Operator *= ( TVar ) ***/
156 
157 template<class TVar>
160 {
161  fMat.fMult( value );
162  this->fDecomposed = 0;
163  return( *this );
164 }
165 
166 
167 
168 /******** Metodos genericos ********/
169 
170 /**************************/
171 /*** Decompose Cholesky ***/
172 template<class TVar>
173 int
174 TPZSSpMatrix<TVar>::Decompose_Cholesky(std::list<int64_t> &singular)
175 {
176  return Decompose_Cholesky();
177 }
178 
179 template<class TVar>
180 int
182 {
183 
184  if ( this->fDecomposed && this->fDecomposed != ECholesky) TPZMatrix<TVar>::Error(__PRETTY_FUNCTION__, "Decompose_Cholesky <Matrix already Decomposed with different algorithm>" );
185  else if(this->fDecomposed) return 0;
186 
187 
189  TPZLink<TPZSpMatrix<REAL>::TPZNode> *row_end = &fMat.fElem[ this->Dim() ];
190  TPZLink<TPZSpMatrix<REAL>::TPZNode> *row_k = &fMat.fElem[ 0 ];
191 
192  for ( int64_t k = 0; k < this->Dim(); k++, row_k++ )
193  {
194  // Faz sum = SOMA( A(k,p) * A(k,p) ), p = 1, ..., k-1.
195  //
196  REAL sum = 0.0;
197  row_k->Head();
198  node_k.col = -1;
199  for (; row_k->Get( &node_k ) && (node_k.col < k);
200  row_k->Next() )
201  sum += node_k.elem * node_k.elem;
202 
203  // Faz A(k,k) = sqrt( A(k,k) - sum ).
204  //
205  node_k.elem -= sum;
206  if ( (node_k.col != k) || (node_k.elem < 1.e-10) )
207  return( 0 );
208  // TPZMatrix::Error(__PRETTY_FUNCTION__, "Cholesky_Decomposition ",
209  // "<matrix is not positive definite>" );
210  if ( node_k.elem < 1.e-10 )
211  return( 0 );
212  // TPZMatrix::Error(__PRETTY_FUNCTION__, "Cholesky_Decomposition <sqrt of negative number>");
213  TVar pivot = node_k.elem = sqrt( node_k.elem );
214  row_k->Update( node_k );
215 
216  // Loop para i = k+1 ... Dim().
217  //
219  TPZLink<TPZSpMatrix<REAL>::TPZNode> *row_i = row_k + 1;
220  for ( ; row_i != row_end; row_i++ )
221  {
222  // Faz sum = SOMA( A(i,p) * A(k,p) ), p = 1, ..., k-1.
223  //
224  sum = ProdEsc( row_k, row_i, k );
225 
226  // Faz A(i,k) = (A(i,k) - sum) / A(k,k)
227  //
228  node_i.col = -1;
229  row_i->Get( &node_i );
230  if ( node_i.col != k )
231  {
232  node_i.elem = -sum / pivot;
233  node_i.col = k;
234  row_i->Insert( node_i );
235  }
236  else
237  {
238  node_i.elem = (node_i.elem - sum) / pivot;
239  row_i->Update( node_i );
240  }
241  }
242  }
243 
244  this->fDecomposed = 1;
245  this->fDefPositive = 1;
246  return( 1 );
247 }
248 
249 
250 
251 /**********************/
252 /*** Decompose LDLt ***/
253 template<class TVar>
254 int
255 TPZSSpMatrix<TVar>::Decompose_LDLt(std::list<int64_t> &singular)
256 {
257  return Decompose_LDLt();
258 }
259 
260 template<class TVar>
261 int
263 {
264  if ( this->fDecomposed && this->fDecomposed != ELDLt) TPZMatrix<TVar>::Error(__PRETTY_FUNCTION__, "Decompose_LDLt <Matrix already Decomposed with different method>" );
265  else if(this->fDecomposed) return 0;
266 
267 
270  TPZLink<TPZSpMatrix<REAL>::TPZNode> *row_k = &fMat.fElem[ 0 ];
271  TPZLink<TPZSpMatrix<REAL>::TPZNode> *row_end = &fMat.fElem[ this->Dim() ];
272 
273  for ( int64_t k = 0; k < this->Dim(); k++, row_k++ )
274  {
275  // Faz aux(p) = A(p,p) * A(k,p), p = 1, ..., k-1.
276  //
277  row_k->Head();
278  row_aux.Clear();
279  for ( ; row_k->Get( &node_k ) && (node_k.col < k);
280  row_k->Next() )
281  {
282  node_k.elem *= GetVal( node_k.col, node_k.col );
283  if ( node_k.elem!=REAL(0.0) )
284  row_aux.Append( node_k );
285  }
286 
287  // Faz sum = SOMA( A(k,p) * aux(p) ), p = 1, ..., k-1.
288  //
289  TVar sum = ProdEsc( row_k, &row_aux, k );
290 
291 
292  // Faz A(k,k) = A(k,k) - sum;
293  //
294  node_k.col = -1;
295  row_k->Get( &node_k );
296  if ( node_k.col != k )
297  {
298  // O elemento antigo A(k,k) e' ZERO...
299  node_k.col = k;
300  node_k.elem = -sum;
301  if ( IsZero( node_k.elem ) )
302  TPZMatrix<REAL> ::Error(__PRETTY_FUNCTION__, "LDLt_Decomposition <diag element is zero>" );
303  row_k->Insert( node_k );
304  }
305  else
306  {
307  // O elemento antigo A(k,k) nao e' ZERO...
308  node_k.elem -= sum;
309  if ( IsZero( node_k.elem ) )
310  TPZMatrix<REAL> ::Error(__PRETTY_FUNCTION__, "LDLt_Decomposition <diag element is zero>" );
311  row_k->Update( node_k );
312  }
313  TVar pivot = node_k.elem;
314 
315  // Loop para i = k+1, ..., Dim().
316  //
318  TPZLink<TPZSpMatrix<REAL>::TPZNode> *row_i = row_k + 1;
319  for ( ; row_i != row_end; row_i++ )
320  {
321  // Faz sum = SOMA( A(i,p) * aux(p) ), p = 1, ..., k-1.
322  //
323  sum = ProdEsc( row_i, &row_aux, k );
324 
325  // Faz A(i,k) = (A(i,k) - sum) / A(k,k).
326  //
327  node_i.col = -1;
328  row_i->Get( &node_i );
329  if ( node_i.col != k )
330  {
331  node_i.col = k;
332  node_i.elem = -sum / pivot;
333  row_i->Insert( node_i );
334  }
335  else
336  {
337  node_i.elem = (node_i.elem - sum) / pivot;
338  row_i->Update( node_i );
339  }
340  }
341  }
342 
343  this->fDecomposed = 1;
344  this->fDefPositive = 0;
345  return( 1 );
346 }
347 
348 
349 
350 /*********************/
351 /*** Subst Forward ***/
352 //
353 // Faz Ax = b, onde A e' triangular inferior.
354 //
355 template<class TVar>
356 int
358 {
359  if ( (B->Rows() != this->Dim()) || !this->fDecomposed )
360  return( 0 );
361 
362  TPZLink<TPZSpMatrix<REAL>::TPZNode> *row_k = &fMat.fElem[0];
363  for ( int64_t k = 0; k < this->Dim(); k++, row_k++ )
364  for ( int64_t j = 0; j < B->Cols(); j++ )
365  {
366  // Faz sum = SOMA( A[k,i] * B[i,j] ), para i = 1, ..., k-1.
367  //
368  TVar sum = 0.0;
370  row_k->Head();
371  for ( ; row_k->Get( &ni ) && (ni.col < k ); row_k->Next() )
372  sum += ni.elem * B->GetVal( ni.col, j );
373 
374  // E' assumido que A[k,k] nunca e' ZERO, pois a matriz
375  // ja' foi decomposta.
376  // A[k,k] == ni.elem, se ni.col == k.
377 
378  // Faz B[k,j] = (B[k,j] - sum) / A[k,k].
379  //
380  B->PutVal( k, j, (B->GetVal( k, j ) - sum) / ni.elem );
381  }
382 
383  return( 1 );
384 }
385 
386 
387 
388 /***********************/
389 /*** Subst L Forward ***/
390 //
391 // Faz a "Forward substitution" assumindo que os elementos
392 // da diagonal sao todos iguais a 1.
393 //
394 
395 template<class TVar>
396 int
398 {
399  if ( (B->Rows() != this->Dim()) || !this->fDecomposed )
400  return( 0 );
401 
402  TPZLink<TPZSpMatrix<REAL>::TPZNode> *row_k = &fMat.fElem[0];
403  for ( int64_t k = 0; k < this->Dim(); k++, row_k++ )
404  for ( int64_t j = 0; j < B->Cols(); j++ )
405  {
406  // Faz sum = SOMA( A[k,i] * B[i,j] ), para i = 1, ..., k-1.
407  //
408  TVar sum = 0.0;
410  row_k->Head();
411  for ( ; row_k->Get( &ni ) && (ni.col < k ); row_k->Next() )
412  sum += ni.elem * B->GetVal( ni.col, j );
413 
414  // Faz b[k] = (b[k] - sum).
415  //
416  B->PutVal( k, j, B->GetVal( k, j ) - sum );
417  }
418 
419  return( 1 );
420 }
421 
422 
423 
424 /******************/
425 /*** Subst Diag ***/
426 //
427 // Faz Ax = B, sendo que A e' assumida ser uma matriz diagonal.
428 //
429 template<class TVar>
430 int
432 {
433  // So' e' permitido fazer esta substituicao se a matriz foi
434  // decomposta, pois desta forma se garante que os elementos
435  // da diagonal sao diferentes de ZERO. O que elimina uma
436  // verificacao.
437  //
438  if ( (B->Rows() != this->Dim()) || !this->fDecomposed )
439  return( 0 );
440 
442  TPZLink<TPZSpMatrix<REAL>::TPZNode> *row_k = &fMat.fElem[0];
443  for ( int64_t k = 0; k < this->Dim(); k++, row_k++ )
444  {
445  row_k->GetLast( &node_kk );
446  for ( int64_t j = 0; j < B->Cols(); j++ )
447  B->PutVal( k, j, B->GetVal( k, j ) / node_kk.elem );
448  }
449  return( 1 );
450 }
451 
452 
453 
454 
455 /**************************** PRIVATE ****************************/
456 
457 
458 
459 /*************/
460 /*** Error ***/
461 /*int
462  TPZSSpMatrix::Error(const char *msg1,const char *msg2 )
463  {
464  ostringstream out;
465  out << "TPZSSpMatrix::" << msg1 << msg2 << ".\n";
466  //pzerror.show();
467  LOGPZ_ERROR (logger, out.str().c_str());
468  DebugStop();
469  return 0;
470  }*/
471 
472 
473 
474 /****************/
475 /*** Prod Esc ***/
476 template<class TVar>
477 TVar
479  TPZLink<TPZSpMatrix<REAL>::TPZNode> *row_j, int64_t k )
480 {
481  TVar prod = 0.0;
482 
483  TPZSpMatrix<REAL>::TPZNode node_i, node_j;
484 
485  row_i->Head();
486  row_j->Head();
487 
488  int64_t again_i = row_i->Get( &node_i ) && (node_i.col < k);
489  int64_t again_j = row_j->Get( &node_j ) && (node_j.col < k);
490 
491  while ( again_i && again_j )
492  {
493  if ( node_i.col > node_j.col )
494  {
495  row_j->Next();
496  again_j = row_j->Get( &node_j ) && (node_j.col < k);
497  }
498  else if ( node_i.col < node_j.col )
499  {
500  row_i->Next();
501  again_i = row_i->Get( &node_i ) && (node_i.col < k);
502  }
503  else if ( node_i.col == node_j.col )
504  {
505  prod += node_i.elem * node_j.elem;
506  row_i->Next();
507  row_j->Next();
508  again_i = row_i->Get( &node_i ) && (node_i.col < k);
509  again_j = row_j->Get( &node_j ) && (node_j.col < k);
510  }
511  }
512 
513  // Garante que a lista 'row_i' esteja na coluna 'k'.
514  while ( again_i )
515  {
516  row_i->Next();
517  again_i = row_i->Get( &node_i ) && (node_i.col < k);
518  }
519 
520  // Garante que a lista 'row_j' esteja na coluna 'k'.
521  while ( again_j )
522  {
523  row_j->Next();
524  again_j = row_j->Get( &node_j ) && (node_j.col < k);
525  }
526 
527  return( prod );
528 }
529 
530 #ifdef OOPARLIB
531 
532 template<class TVar>
533 int TPZSSpMatrix<TVar>::Unpack (TReceiveStorage *buf ){
534  TSimMatrix::Unpack(buf);
535  int64_t class_id;
536  buf->UpkLong(&class_id);
537  if(!fMat.DerivedFrom(class_id)) DebugStop();
538  fMat.Unpack(buf);
539  return 1;
540 }
541 
542 
543 template<class TVar>
544 TSaveable *TPZSSpMatrix<TVar>::CreateInstance(TReceiveStorage *buf) {
546  m->Unpack(buf);
547  return m;
548 }
549 
550 template<class TVar>
551 int TPZSSpMatrix<TVar>::Pack( TSendStorage *buf ) const {
552  TSimMatrix::Pack(buf);
553  fMat.Pack(buf);
554  return 1;
555 }
556 
557 template<class TVar>
558 int TPZSSpMatrix<TVar>::DerivedFrom(const int64_t Classid) const {
559  return TSimMatrix::DerivedFrom(Classid);
560 }
561 
562 template<class TVar>
563 int TPZSSpMatrix<TVar>::DerivedFrom(const char *classname) const {
564  if(!strcmp(ClassName(),classname)) return 1;
565  return TSimMatrix::DerivedFrom(classname);
566 }
567 
568 
569 #endif
570 
TPZSSpMatrix operator+(const TPZSSpMatrix< TVar > &A) const
Definition: pzsespmat.cpp:61
Definition: pzmatrix.h:52
bool IsZero(long double a)
Returns if the value a is close Zero as the allowable tolerance.
Definition: pzreal.h:668
Contains definitions to LOGPZ_DEBUG, LOGPZ_INFO, LOGPZ_WARN, LOGPZ_ERROR and LOGPZ_FATAL, and the implementation of the inline InitializePZLOG(string) function using log4cxx library or not. It must to be called out of "#ifdef LOG4CXX" scope.
static int Error(const char *msg, const char *msg2=0)
Returns error messages.
Definition: pzmatrix.cpp:1402
TPZSSpMatrix & operator*=(const TVar v)
Definition: pzsespmat.cpp:159
Contains TPZSSpMatrix class which implements sparse symmetric matrix using a linked list of elements...
int64_t fRow
Number of rows in matrix.
Definition: pzmatrix.h:779
TPZSpMatrix< TVar > fMat
Definition: pzsespmat.h:111
TVar ProdEsc(TPZLink< TPZSpMatrix< REAL >::TPZNode > *row_i, TPZLink< TPZSpMatrix< REAL >::TPZNode > *row_j, int64_t k)
Calcula o produto escalar entre as linhas &#39;row_i&#39; e &#39;row_j&#39; usando apenas os elementos pertencentes &#39;...
Definition: pzsespmat.cpp:478
char fDecomposed
Decomposition type used to decompose the current matrix.
Definition: pzmatrix.h:783
int Subst_Diag(TPZFMatrix< TVar > *b) const
Computes B = Y, where A*Y = B, A is diagonal matrix.
Definition: pzsespmat.cpp:431
char fDefPositive
Definite Posistiveness of current matrix.
Definition: pzmatrix.h:785
const TVar & GetVal(const int64_t row, const int64_t col) const
Get values without bounds checking This method is faster than "Get" if DEBUG is defined.
Definition: pzsespmat.h:144
TPZSSpMatrix & operator+=(const TPZSSpMatrix< TVar > &A)
Definition: pzsespmat.cpp:94
Implements sparce symmetric matrix using a linked list of elements. Matrix.
Definition: pzespmat.h:27
Defines a node.
Definition: pzespmat.h:49
int Subst_Forward(TPZFMatrix< TVar > *b) const
Computes B = Y, where A*Y = B, A is lower triangular.
Definition: pzsespmat.cpp:357
TPZSSpMatrix & operator-=(const TPZSSpMatrix< TVar > &A)
Definition: pzsespmat.cpp:111
Contains TPZMatrixclass which implements full matrix (using column major representation).
#define DebugStop()
Returns a message to user put a breakpoint in.
Definition: pzerror.h:20
int Subst_LForward(TPZFMatrix< TVar > *b) const
Computes B = Y, where A*Y = B, A is lower triangular with A(i,i)=1.
Definition: pzsespmat.cpp:397
int64_t Rows() const
Returns number of rows.
Definition: pzmatrix.h:803
static TPZSavable * CreateInstance(const int &classId)
Definition: TPZSavable.cpp:120
expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ expr_ sqrt
Definition: tfadfunc.h:120
string res
Definition: test.py:151
Full matrix class. Matrix.
Definition: pzfmatrix.h:32
virtual int64_t Dim() const
Returns the dimension of the matrix if the matrix is square.
Definition: pzmatrix.h:892
int Decompose_LDLt()
Decomposes the current matrix using LDLt.
Definition: pzsespmat.cpp:262
int64_t fCol
Number of cols in matrix.
Definition: pzmatrix.h:781
TPZSSpMatrix & operator=(const TPZSSpMatrix< TVar > &A)
Operators with SYMMETRIC sparse matrices.
Definition: pzsespmat.cpp:45
TPZSSpMatrix operator-(const TPZSSpMatrix< TVar > &A) const
Definition: pzsespmat.cpp:77
int64_t Cols() const
Returns number of cols.
Definition: pzmatrix.h:809
clarg::argString m("-m", "input matrix file name (text format)", "matrix.txt")
int PutVal(const int64_t row, const int64_t col, const TVar &value) override
Put values without bounds checking This method is faster than "Put" if DEBUG is defined.
Definition: pzfmatrix.h:548
const TVar & GetVal(const int64_t row, const int64_t col) const override
Get values without bounds checking This method is faster than "Get" if DEBUG is defined.
Definition: pzfmatrix.h:566
int Decompose_Cholesky()
Decomposes the current matrix using Cholesky method. The current matrix has to be symmetric...
Definition: pzsespmat.cpp:181
TPZSSpMatrix operator*(const TVar v) const
Operators with numeric values.
Definition: pzsespmat.cpp:144
Root matrix class (abstract). Matrix.
Definition: pzmatrix.h:60