OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
skyline.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 #include "skyline.h"
36 #include "floatmatrix.h"
37 #include "intarray.h"
38 #include "domain.h"
39 #include "engngm.h"
40 #include "element.h"
41 #include "mathfem.h"
42 #include "verbose.h"
43 #include "sparsemtrxtype.h"
44 #include "classfactory.h"
45 #include "activebc.h"
46 #include "contact/contactmanager.h"
48 #include "contact/contactelement.h"
49 #include "unknownnumberingscheme.h"
50 
51 
52 #include <climits>
53 #include <cstdlib>
54 
55 #ifdef TIME_REPORT
56  #include "timer.h"
57 #endif
58 
59 namespace oofem {
61 
63 {
64  // constructor
65  // skyline is square mtrx, so size is n,n
66  //
67  nwk = 0;
68  mtrx = NULL;
69  isFactorized = false;
70 }
71 
72 
74 {
75  // Constructor. Creates a skyline of size 0.
76  // nRows = nColumns = 0; // set by SparseMtrx constructor
77  nwk = 0;
78  mtrx = NULL;
79  isFactorized = false;
80 }
81 
82 
84 {
85  // Destructor.
86  if ( this->giveNumberOfRows() ) {
87  free(mtrx);
88  }
89 }
90 
91 
92 double &
93 Skyline :: at(int i, int j)
94 {
95  // returns (i,j) element of the receiver
96  // indexes are checked if DEBUG is true
97 
98  int d1, k, ind;
99 
100 #ifdef DEBUG
101  // check size
102  if ( ( i > this->giveNumberOfRows() ) || ( j > this->giveNumberOfRows() ) ) {
103  OOFEM_ERROR("dimension mismatch - accessing value at (%d,%d)", i, j);
104  }
105 
106 #endif
107  // only upper triangular part of skyline is stored
108  if ( j < i ) {
109  k = i;
110  i = j;
111  j = k;
112  }
113 
114  d1 = this->adr.at(j);
115  ind = d1 + ( j - i );
116 
117  if ( ( adr.at(j + 1) - adr.at(j) ) <= ( j - i ) ) {
118  OOFEM_ERROR("request for element which is not in sparse mtrx (%d,%d)", i, j);
119  //
120  // NOTE:
121  //
122  // don't return reference to some zero value; it is true, but possible change
123  // of its value will require rebuilding internal storage structure
124  // of sparse matrix
125  //
126  }
127 
128  // increment version flag
129  this->version++;
130  return mtrx [ ind ];
131 }
132 
133 double
134 Skyline :: at(int i, int j) const
135 {
136  // returns (i,j) element of the receiver
137  // indexes are checked if DEBUG is true
138 
139  int d1, k, ind;
140 
141 #ifdef DEBUG
142  // check size
143  if ( ( i > this->giveNumberOfRows() ) || ( j > this->giveNumberOfRows() ) ) {
144  OOFEM_ERROR("dimension mismatch, when accessing value at (%d,%d)", i, j);
145  }
146 
147 #endif
148  // only upper triangular part of skyline is stored
149  if ( j < i ) {
150  k = i;
151  i = j;
152  j = k;
153  }
154 
155  d1 = this->adr.at(j);
156  ind = d1 + ( j - i );
157 
158  if ( ( adr.at(j + 1) - adr.at(j) ) <= ( j - i ) ) {
159  OOFEM_ERROR("request for element which is not in sparse mtrx (%d,%d)", i, j);
160  //
161  // NOTE:
162  //
163  // don't return reference to some zero value; it is true, but possible change
164  // of its value will require rebuilding internal storage structure
165  // of sparse matrix
166  //
167  }
168 
169  return mtrx [ ind ];
170 }
171 
172 
173 bool
174 Skyline :: isAllocatedAt(int i, int j) const
175 {
176  int k, answer = 1;
177 
178  if ( j < i ) {
179  k = i;
180  i = j;
181  j = k;
182  }
183 
184  if ( ( adr.at(j + 1) - adr.at(j) ) <= ( j - i ) ) {
185  answer = 0;
186  }
187 
188  return (bool)answer;
189 }
190 
191 
192 void
194 {
195  // Returns a matrix, the receiver in a full storage form. This is useful
196  // for debugging and printings.
197 
198  int d1, d2, pk, size;
199 
200  size = this->giveNumberOfColumns();
201 
202 # ifdef DEBUG
203  if ( size != this->adr.giveSize() - 1 ) {
204  OOFEM_ERROR("Internal error in skyline matrix: num columns != size(adr)-1: %d != %d", size, this->adr.giveSize() - 1);
205  }
206 # endif
207 
208  answer.resize(size, size);
209  answer.zero();
210 
211  for ( int j = 1; j <= size; j++ ) {
212  d1 = adr.at(j);
213  d2 = adr.at(j + 1);
214  pk = j;
215  for ( int i = d1; i < d2; i++ ) {
216  answer.at(pk, j) = mtrx [ i ];
217  pk--;
218  }
219  }
220  answer.symmetrized();
221 }
222 
223 
224 int Skyline :: assemble(const IntArray &loc, const FloatMatrix &mat)
225 {
226  // Assembles the elemental matrix 'mat' to the receiver, using 'loc' as a
227  // location array. The values in ke corresponding to a zero coefficient
228  // in loc are not assembled.
229 
230 # ifdef DEBUG
231  int dim = mat.giveNumberOfRows();
232  if ( dim != loc.giveSize() ) {
233  OOFEM_ERROR("dimension of 'mat' and 'loc' mismatch");
234  }
235 
236 # endif
237 
238  int ndofe = mat.giveNumberOfRows();
239 
240  for ( int i = 1; i <= ndofe; i++ ) {
241  int ac1 = loc.at(i);
242  if ( ac1 == 0 ) {
243  continue;
244  }
245 
246  for ( int j = 1; j <= ndofe; j++ ) {
247  int ac2 = loc.at(j);
248  if ( ac2 == 0 ) {
249  continue;
250  }
251 
252  if ( ac1 > ac2 ) {
253  continue;
254  }
255 
256  mtrx [ adr.at(ac2) + ac2 - ac1 ] += mat.at(i, j);
257  }
258  }
259 
260  // increment vesion
261  this->version++;
262  return 1;
263 }
264 
265 
266 int Skyline :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat)
267 {
268  int dim1 = mat.giveNumberOfRows();
269  int dim2 = mat.giveNumberOfColumns();
270  for ( int i = 1; i <= dim1; i++ ) {
271  int ii = rloc.at(i);
272  if ( ii ) {
273  for ( int j = 1; j <= dim2; j++ ) {
274  int jj = cloc.at(j);
275  if ( jj && ii <= jj ) {
276  this->at(ii, jj) += mat.at(i, j);
277  }
278  }
279  }
280  }
281 
282  // increment version
283  this->version++;
284 
285  return 1;
286 }
287 
288 
290 // Returns the solution x of the system U.x = y , where U is the receiver.
291 // note : x overwrites y
292 {
293  // allocation of answer
294  FloatArray solution( y.giveSize() );
295  int ack, ack1, acs, n;
296  int size = this->giveNumberOfRows();
297 
298  /************************************/
299  /* modification of right hand side */
300  /************************************/
301  n = size;
302  for ( int k = 2; k <= n; k++ ) {
303  ack = adr.at(k);
304  ack1 = adr.at(k + 1);
305  double s = 0.0;
306  acs = k - ( ack1 - ack ) + 1;
307  for ( int i = ack1 - 1; i > ack; i-- ) {
308  s += mtrx [ i ] * y.at(acs);
309  acs++;
310  }
311 
312  y.at(k) -= s;
313  }
314 
315  /*****************/
316  /* zpetny chod */
317  /*****************/
318  for ( int k = 1; k <= n; k++ ) {
319  acs = adr.at(k);
320  y.at(k) /= mtrx [ acs ];
321  }
322 
323  for ( int k = n; k > 0; k-- ) {
324  ack = adr.at(k);
325  ack1 = adr.at(k + 1);
326  solution.at(k) = y.at(k);
327  acs = k - ( ack1 - ack ) + 1;
328  for ( int i = ack1 - 1; i > ack; i-- ) {
329  y.at(acs) -= mtrx [ i ] * solution.at(k);
330  acs++;
331  }
332  }
333 
334  y = solution;
335  return & y;
336 }
337 
339 {
340  // allocates and built structure according to given
341  // array of maximal column heights
342  //
343  adr = a;
344  int n = a.giveSize();
345  nwk = adr.at(n); // check
346  if ( mtrx ) {
347  free(mtrx);
348  }
349 
350  mtrx = ( double * ) calloc( nwk, sizeof( double ) );
351  if ( !mtrx ) {
352  OOFEM_ERROR("Can't allocate: %d", nwk);
353  }
354  nRows = nColumns = n - 1;
355 
356  // increment version
357  this->version++;
358  return true;
359 }
360 
361 
363 {
364  // first create array of
365  // maximal column height for assembled characteristics matrix
366  //
367 
368  int maxle;
369  int ac1;
370  int neq;
371  if ( s.isDefault() ) {
372  neq = eModel->giveNumberOfDomainEquations(di, s);
373  } else {
375  }
376  if ( neq == 0 ) {
377  if ( mtrx ) {
378  delete mtrx;
379  }
380  mtrx = NULL;
381  adr.clear();
382  return true;
383  }
384 
385  IntArray loc;
386  IntArray mht(neq);
387  Domain *domain = eModel->giveDomain(di);
388 
389  for ( int j = 1; j <= neq; j++ ) {
390  mht.at(j) = j; // initialize column height, maximum is line number (since it only stores upper triangular)
391  }
392 
393  // loop over elements code numbers
394  for ( auto &elem : domain->giveElements() ) {
395  elem->giveLocationArray(loc, s);
396  maxle = INT_MAX;
397  for ( int ieq : loc ) {
398  if ( ieq != 0 ) {
399  maxle = min(maxle, ieq);
400  }
401  }
402 
403  for ( int ieq : loc ) {
404  if ( ieq != 0 ) {
405  mht.at(ieq) = min( maxle, mht.at(ieq) );
406  }
407  }
408  }
409 
410  // loop over active boundary conditions (e.g. relative kinematic constraints)
411  std :: vector< IntArray >r_locs;
412  std :: vector< IntArray >c_locs;
413 
414  for ( auto &gbc : domain->giveBcs() ) {
415  ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() );
416  if ( bc != NULL ) {
417  bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s);
418  for ( std :: size_t k = 0; k < r_locs.size(); k++ ) {
419  IntArray &krloc = r_locs [ k ];
420  IntArray &kcloc = c_locs [ k ];
421  maxle = INT_MAX;
422  for ( int ii : krloc ) {
423  if ( ii > 0 ) {
424  maxle = min(maxle, ii);
425  }
426  }
427  for ( int jj : kcloc ) {
428  if ( jj > 0 ) {
429  mht.at(jj) = min( maxle, mht.at(jj) );
430  }
431  }
432  }
433  }
434  }
435 
436 
437  if ( domain->hasContactManager() ) {
438  ContactManager *cMan = domain->giveContactManager();
439 
440  for ( int i =1; i <= cMan->giveNumberOfContactDefinitions(); i++ ) {
441  ContactDefinition *cDef = cMan->giveContactDefinition(i);
442  for ( int k = 1; k <= cDef->giveNumbertOfContactElements(); k++ ) {
443  ContactElement *cEl = cDef->giveContactElement(k);
444  cEl->giveLocationArray(loc, s);
445 
446  maxle = INT_MAX;
447  for ( int ieq : loc ) {
448  if ( ieq != 0 ) {
449  maxle = min(maxle, ieq);
450  }
451  }
452 
453  for ( int ieq : loc ) {
454  if ( ieq != 0 ) {
455  mht.at(ieq) = min( maxle, mht.at(ieq) );
456  }
457 
458  }
459  }
460  }
461  }
462 
463  // NOTE
464  // add there call to eModel if any possible additional equation added by
465  // eModel
466  // currently not supported
467 
468  // increases number of columns according to size of mht
469  // mht is array containing minimal equation number per column
470  // This method also increases column height.
471 
472 
473  adr.resize(neq + 1);
474 
475  ac1 = 1;
476  for ( int i = 1; i <= neq; i++ ) {
477  adr.at(i) = ac1;
478  ac1 += ( i - mht.at(i) + 1 );
479  }
480 
481  adr.at(neq + 1) = ac1;
482  nRows = nColumns = neq;
483  nwk = ac1;
484  if ( mtrx ) {
485  free(mtrx);
486  }
487 
488  mtrx = ( double * ) calloc( ac1, sizeof( double ) );
489  if ( !mtrx ) {
490  OOFEM_ERROR("Can't allocate: %d", ac1);
491  }
492 
493  // increment version
494  this->version++;
495  return true;
496 }
497 
498 
500 {
501  // Returns the receiver in U(transp).D.U Crout factorization form.
502 
503  int aci, aci1, acj, acj1, ack, ack1, ac, acs, acri, acrk, n;
504  double s, g;
505 
506  /************************/
507  /* matrix elimination */
508  /************************/
509  if ( isFactorized ) {
510  return this;
511  }
512 
513 #ifdef TIME_REPORT
514  Timer timer;
515  timer.startTimer();
516 #endif
517 
518  n = this->giveNumberOfRows();
519 
520  // report skyline statistics
521  OOFEM_LOG_DEBUG("Skyline info: neq is %d, nwk is %d\n", n, this->nwk);
522 
523  for ( int k = 2; k <= n; k++ ) {
524  /* smycka pres sloupce matice */
525  ack = adr.at(k);
526  ack1 = adr.at(k + 1);
527  acrk = k - ( ack1 - ack ) + 1;
528  for ( int i = acrk + 1; i < k; i++ ) {
529  /* smycka pres prvky jednoho sloupce matice */
530  aci = adr.at(i);
531  aci1 = adr.at(i + 1);
532  acri = i - ( aci1 - aci ) + 1;
533  if ( acri < acrk ) {
534  ac = acrk;
535  } else {
536  ac = acri;
537  }
538 
539  acj = k - ac + ack;
540  acj1 = k - i + ack;
541  acs = i - ac + aci;
542  s = 0.0;
543  for ( int j = acj; j > acj1; j-- ) {
544  s += mtrx [ j ] * mtrx [ acs ];
545  acs--;
546  }
547 
548  mtrx [ acj1 ] -= s;
549  }
550 
551  /* uprava diagonalniho prvku */
552  s = 0.0;
553  for ( int i = ack1 - 1; i > ack; i-- ) {
554  g = mtrx [ i ];
555  acs = adr.at(acrk);
556  acrk++;
557  mtrx [ i ] /= mtrx [ acs ];
558  s += mtrx [ i ] * g;
559  }
560 
561  mtrx [ ack ] -= s;
562  }
563 
564  isFactorized = true;
565 
566 #ifdef TIME_REPORT
567  timer.stopTimer();
568  OOFEM_LOG_DEBUG( "Skyline info: user time consumed by factorization: %.2fs\n", timer.getUtime() );
569 #endif
570 
571  // increment version
572  //this->version++;
573  return this;
574 }
575 
576 
577 
578 void Skyline :: times(const FloatArray &x, FloatArray &answer) const
579 {
580  // Computes y, the results of the y = U.x, where U is
581  // the receiver. Returns the result.
582 
583  int k, acb, acc, aci, aci1, ac, n;
584  double s;
585 
586  //
587  // first check sizes
588  //
589  if ( this->giveNumberOfRows() != ( n = x.giveSize() ) ) {
590  OOFEM_ERROR("size mismatch");
591  }
592 
593  answer.resize(n);
594  answer.zero();
595 
596  acc = 1;
597  for ( int i = 1; i <= n; i++ ) {
598  aci = adr.at(i);
599  aci1 = adr.at(i + 1);
600  ac = i - ( aci1 - aci ) + 1;
601  s = 0.0;
602  acb = ac;
603  for ( k = aci1 - 1; k >= aci; k-- ) {
604  s += mtrx [ k ] * x.at(acb);
605  acb++;
606  }
607 
608  answer.at(acc) = s;
609  acc++;
610 
611  for ( int j = ac; j < i; j++ ) {
612  aci1--;
613  s = mtrx [ aci1 ];
614  answer.at(j) += s * x.at(i);
615  aci++;
616  }
617  }
618 }
619 
620 
621 void Skyline :: times(double x)
622 {
623  // Multiplies receiver by scalar value.
624  for ( int j = 0; j < nwk; j++ ) {
625  mtrx [ j ] *= x;
626  }
627 
628  // increment version
629  this->version++;
630 }
631 
632 
633 void Skyline :: add(double x, SparseMtrx &m)
634 {
635  Skyline *M = dynamic_cast< Skyline* >( &m );
636 
637  for ( int j = 0; j < nwk; j++ ) {
638  mtrx [ j ] += x * M->mtrx [ j ];
639  }
640 
641  this->version++;
642 }
643 
645 {
646  // Prints the receiver on screen.
647  FloatMatrix copy;
648 
649  this->toFloatMatrix(copy);
650  copy.printYourself();
651 }
652 
653 
654 void Skyline :: writeToFile(const char *fname) const
655 {
656  FILE *file = fopen(fname, "w");
657  FloatMatrix copy;
658  this->toFloatMatrix(copy);
659  for ( int i = 1; i <= nRows; ++i ) {
660  for ( int j = 1; j <= nColumns; ++j ) {
661  fprintf( file, "%10.3e ", copy.at(i, j) );
662  }
663  fprintf(file, "\n");
664  }
665  fclose(file);
666 }
667 
668 
670 {
671  // Returns the receiver with all coefficients set to zero.
672  for ( int j = 0; j < nwk; j++ ) {
673  mtrx [ j ] = 0.0;
674  }
675 
676  isFactorized = false;
677 
678  // increment version
679  this->version++;
680 }
681 
683 {
684  Skyline *answer;
685  double *mtrx1;
686  int neq;
687 
688  neq = this->giveNumberOfRows();
689 
690  mtrx1 = ( double * ) malloc( this->nwk * sizeof( double ) );
691  if ( !mtrx1 ) {
692  OOFEM_ERROR("Can't allocate: %d", this->nwk);
693  }
694 
695  for ( int i = 0; i < this->nwk; i++ ) {
696  mtrx1 [ i ] = this->mtrx [ i ];
697  }
698 
699  answer = new Skyline(neq, this->nwk, mtrx1, adr);
700 
701  return answer;
702 }
703 
704 Skyline :: Skyline(int neq, int nwk1, double *mtrx1, const IntArray &adr1) : SparseMtrx(neq, neq)
705 {
706  // constructor
707  // sets internal member data to given parameters
708  // used only by GiveCopy() member function
709 
710  nwk = nwk1;
711  mtrx = mtrx1;
712  adr = adr1;
713  isFactorized = 0;
714 }
715 
716 
717 //Skyline *Skyline :: giveSubMatrix(Skyline &mat, IntArray &rows, IntArray &cols)
718 //Skyline *Skyline :: beSubMatrixOf(const Skyline &mat, IntArray &rows, IntArray &cols)
719 //SparseMtrx *Skyline :: beSubMatrixOf(const SparseMtrx &mat, IntArray &rows, IntArray &cols)
721 {
722 
723  IntArray positions( cols.giveSize() + 1 );
724 
725  FloatArray values( this->giveNumberOfNonZeros() ); //TODO choose a better initial size?
726  int diagPos = 1;
727  int nnz = 0; // number of nonzeros
728 
729  for ( int j = 1; j <= cols.giveSize(); j++ ) {
730  for ( int i = rows.giveSize(); i >= 1; i-- ) { // start from the "bottom of the matrix"
731  //if( cols.at(j) < rows.at(i) ){
732  if( j < i ){
733  continue;
734  }
735 
736  bool hasValue = this->isAllocatedAt( rows.at(i), cols.at(j) );
737 
738  if ( hasValue && i == j ) { // allocated diagonal element
739  values.at(++nnz) = this->at( rows.at(i), cols.at(j) );
740  positions.at(diagPos++) = nnz;
741  } else if ( i == j ) { // empty diagonal element
742  values.at(++nnz) = 0.0;
743  positions.at(diagPos++) = nnz;
744  } else if ( hasValue ) {
745  values.at(++nnz) = this->at( rows.at(i), cols.at(j) );
746  }
747 
748  }
749  }
750 
751  positions.at(diagPos++) = ++nnz;
752 
753  double *mtrxValues;
754  mtrxValues = ( double * ) malloc( nnz * sizeof( double ) );
755  if ( !mtrxValues ) {
756  OOFEM_ERROR("Can't allocate: %d", nnz);
757  }
758 
759  for ( int i = 0; i < nnz-1; i++ ) {
760  mtrxValues [ i + 1] = values [ i ];
761  }
762  int neq = rows.giveSize();
763 
764  Skyline *answer = new Skyline(neq, nnz, mtrxValues, positions);
765 
766 
767 
768  //this->adr.printYourself();
769  //answer->adr.printYourself();
770  //this->printYourself();
771 
772  for ( int i = 0; i < nnz; i++ ) {
773  // printf("old %e, new %e \n", this->mtrx[i], answer->mtrx[i]);
774  //answer->mtrx.printYourself();
775  }
776 
777 
778 
779  return answer;
780 
781 }
782 
783 
784 
785 void Skyline :: rbmodes(FloatMatrix &r, int &nse, IntArray &se,
786  double limit, int tc)
787 {
788  /*
789  * funkce rozlozi matici A na LDL tvar, pak vypocte
790  * bazove vektory prostoru Ker A
791  */
792  int i, j, k, ii, jj, kk, lj, uj, li, ui, lk, uk, mi, ise, ib, neq = this->giveNumberOfRows();
793  IntArray adrb(7);
794  double s, g;
795  FloatArray b(6 *neq);
796 
797  /**********************/
798  /* rozklad matice A */
799  /**********************/
800 
801  // report skyline statistics
802  OOFEM_LOG_INFO("Skyline info: neq is %d, nwk is %d\n", neq, this->nwk);
803 
804  if ( tc == 1 || tc == 3 ) {
805  /* pocitadlo singularnich rovnic */
806  ise = 1;
807  /* pocitadlo v poli singularnich radku */
808  ib = 1;
809  adrb.at(1) = 1;
810 
811  /* cyklus pres radky, ktere maji byt odkondezovany */
812  for ( i = 2; i <= neq; i++ ) {
813  lj = adr.at(i);
814  uj = adr.at(i + 1) - 2;
815 
816  /* minimalni radkovy index v i tem sloupci */
817  mi = i - ( uj - lj ) - 1;
818  j = mi + 1;
819 
820  /* cyklus pres mimodiagonalni prvky zpracovavaneho radku */
821  for ( jj = uj; jj > lj; jj-- ) {
822  li = adr.at(j);
823  ui = adr.at(j + 1) - 1;
824  k = j - ( ui - li );
825 
826  /* vyber nizsiho sloupce a tim urceni rozsahu cyklu */
827  if ( k < mi ) {
828  uk = uj + 1;
829  ii = li + j - mi;
830  } else {
831  uk = lj + i - k;
832  ii = ui;
833  }
834 
835  /* cyklus pres prvky nad zpracovavanym prvkem */
836  s = 0.0;
837  for ( kk = uk; kk > jj; kk-- ) {
838  s += mtrx [ kk ] * mtrx [ ii ];
839  ii--;
840  }
841 
842  mtrx [ jj ] -= s;
843  j++;
844  }
845 
846  /* uprava diagonalniho prvku */
847  s = 0.0;
848  j = mi;
849  for ( jj = uj + 1; jj > lj; jj-- ) {
850  g = mtrx [ jj ];
851  mtrx [ jj ] /= mtrx [ adr.at(j) ];
852  s += mtrx [ jj ] * g;
853  j++;
854  }
855 
856  mtrx [ lj ] -= s;
857 
858  /* kontrola diagonalniho prvku */
859  if ( fabs(mtrx [ lj ]) < limit ) {
860  /* pole cisel singularnich rovnic */
861  se.at(ise) = i;
862  ise++;
863 
864  /* vynulovani prvku sloupce v poli a a jejich uchovani v poli b */
865  for ( jj = uj + 1; jj > lj; jj-- ) {
866  b.at(ib) = mtrx [ jj ];
867  ib++;
868  mtrx [ jj ] = 0.0;
869  }
870 
871  mtrx [ lj ] = 1.0;
872  /* pole adres zacatku v poli obsahujicim singularni radky */
873  adrb.at(ise) = ib;
874 
875  /* vynulovani prvku radku v poli a */
876  for ( j = i + 1; j <= neq; j++ ) {
877  if ( j - ( adr.at(j + 1) - adr.at(j) ) < i ) {
878  mtrx [ adr.at(j) + j - i ] = 0.0;
879  }
880  }
881  }
882  }
883 
884  nse = ise - 1;
885  }
886 
887  if ( tc == 2 || tc == 3 ) {
888  /* navrat puvodne vynulovanych slozek */
889  ise = nse;
890  for ( i = 1; i <= ise; i++ ) {
891  uj = adr.at(se.at(i) + 1) - 1;
892  lj = adr.at( se.at(i) );
893  ib = adrb.at(i);
894  for ( jj = uj; jj > lj; jj-- ) {
895  mtrx [ jj ] = b.at(ib);
896  ib++;
897  }
898  }
899 
900  /* sestaveni baze ker A */
901  if ( ise ) {
902  r.resize(neq, ise);
903  r.zero();
904  } else {
905  r.clear();
906  }
907 
908  for ( i = 1; i <= ise; i++ ) {
909  // ib=i*neq;
910  for ( j = neq; j > 0; j-- ) {
911  r.at(se.at(i), i) = 1.0;
912  s = r.at(j, i);
913  uk = adr.at(j + 1) - 1;
914  lk = adr.at(j);
915  k = j - ( uk - lk );
916  for ( kk = uk; kk > lk; kk-- ) {
917  r.at(k, i) -= mtrx [ kk ] * s;
918  k++;
919  }
920  }
921  }
922  }
923 
924  // increment version
925  //this->version++;
926 }
927 
928 
929 
930 
931 
933  int nse, double limit, IntArray &se)
934 /*
935  * funkce resi cast soustavy rovnic v metode FETI
936  * matice soustavy a je ulozena ve skyline
937  * matice soustavy muze byt singularni
938  * matice soustavy musi byt jiz rozlozena na tvar LDL
939  *
940  * vstupy
941  * y - vektor prave strany
942  * adr - pole adres diagonalnich prvku
943  * n - pocet neznamych
944  * m - pocet neznamych redukovaneho problemu
945  * nse - pocet linearne zavislych rovnic
946  * limit - promenna urcujici linearni zavislost
947  * se - pole cisel singularnich rovnic
948  *
949  * vystupy
950  * x - vektor reseni
951  *
952  * 8.2.1999
953  */
954 {
955  long i, j, k, ii, lj, uj, neq;
956  double s;
957 
958  neq = this->giveNumberOfRows();
959 
960  /*******************************************************/
961  /* vypocet pomocneho vektoru z */
962  /* vektor prave strany ma na prvnich m pozicich nuly */
963  /* pro vektor z se nealokuje nove pole */
964  /* slozky vektoru y se prepisuji na slozky vektoru z */
965  /*******************************************************/
966  //k = 0;
967  for ( i = 1; i <= neq; i++ ) {
968  lj = adr.at(i);
969  uj = adr.at(i + 1) - 1;
970  ii = i - uj + lj;
971  s = 0.0;
972  for ( j = uj; j > lj; j-- ) {
973  s += mtrx [ j ] * y.at(ii);
974  ii++;
975  }
976 
977  /*
978  * if (se[k]==i){
979  * y[i]=0.0; k++;
980  * }
981  * else{
982  */
983 
984  y.at(i) -= s;
985 
986  /* }*/
987  }
988 
989  /********************************************************/
990  /* kontrola zeliminovaneho vektoru prave strany */
991  /* pokud na nektere pozici se[i] bude nenulove cislo, */
992  /* je soustava neresitelna, protoze se lisi hodnosti */
993  /* matice soustavy a rozsirene matice soustavy */
994  /********************************************************/
995 
996  /*
997  * fprintf (s2,"\n");
998  * for (i=1;i<=nse;i++){
999  * fprintf (s2,"\n eliminovana prava strana singularni rovnice %ld %le",se->at(i),y->at(se->at(i)));
1000  */
1001  /*
1002  * if (fabs(y[se[i]])>limit){
1003  * fprintf (s2,"\n\n v %ld. linearne zavisle rovnici je nenulovy prvek",se[i]);
1004  * fprintf (s2,"\n ve vektoru zeliminovane prave strany.");
1005  * }
1006  */
1007  /*
1008  * }
1009  */
1010 
1011  /**********************************************************/
1012  /* deleni prvku vektoru prave strany diagonalnimi prvky */
1013  /**********************************************************/
1014  for ( i = 1; i <= neq; i++ ) {
1015  y.at(i) /= mtrx [ adr.at(i) ];
1016  }
1017 
1018  /*****************************************************/
1019  /* vypocet vektoru x z vektoru z */
1020  /* vypocet se provadi pro m redukovanych neznamych */
1021  /*****************************************************/
1022  k = nse;
1023  for ( i = neq; i > 0; i-- ) {
1024  lj = adr.at(i);
1025  uj = adr.at(i + 1);
1026  if ( k > 0 ) {
1027  if ( se.at(k) == i ) {
1028  y.at(i) = 1.0;
1029  k--;
1030  }
1031  }
1032 
1033  x.at(i) = y.at(i);
1034  s = x.at(i);
1035  ii = i - 1;
1036  for ( j = lj + 1; j < uj; j++ ) {
1037  y.at(ii) -= s * mtrx [ j ];
1038  ii--;
1039  }
1040  }
1041 
1042  // increment version
1043  //this->version++;
1044 }
1045 } // end namespace oofem
int nColumns
Number of columns.
Definition: sparsemtrx.h:69
int giveNumberOfColumns() const
Returns number of columns of receiver.
Definition: floatmatrix.h:158
virtual int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &)
Builds internal structure of receiver.
Definition: skyline.C:362
virtual void toFloatMatrix(FloatMatrix &answer) const
Converts receiving sparse matrix to a dense float matrix.
Definition: skyline.C:193
Class and object Domain.
Definition: domain.h:115
virtual int giveNumberOfDomainEquations(int di, const UnknownNumberingScheme &num)
Returns number of equations for given domain in active (current time step) time step.
Definition: engngm.C:391
virtual bool isAllocatedAt(int i, int j) const
Returns 0 if the memory is not allocated at position (i,j).
Definition: skyline.C:174
Base class for all matrices stored in sparse format.
Definition: sparsemtrx.h:60
virtual SparseMtrx * GiveCopy() const
Returns a newly allocated copy of receiver.
Definition: skyline.C:682
virtual SparseMtrx * giveSubMatrix(const IntArray &rows, const IntArray &cols)
Definition: skyline.C:720
virtual double & at(int, int)
Returns coefficient at position (i,j).
Definition: skyline.C:93
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
int isFactorized
Flag indicating whether factorized.
Definition: skyline.h:78
virtual void writeToFile(const char *fname) const
Helpful for debugging, writes the matrix to given file.
Definition: skyline.C:654
IntArray adr
Integer array holding addresses of diagonal members.
Definition: skyline.h:74
void ldl_feti_sky(FloatArray &x, FloatArray &y, int nse, double limit, IntArray &se)
Solves the singular system of equations, the receiver should be factorized using rbmodes service...
Definition: skyline.C:932
#define OOFEM_LOG_DEBUG(...)
Definition: logger.h:128
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
Class implementing sparse matrix stored in skyline form.
Definition: skyline.h:68
virtual void times(const FloatArray &x, FloatArray &answer) const
Evaluates .
Definition: skyline.C:578
int nRows
Number of rows.
Definition: sparsemtrx.h:67
virtual void giveLocationArray(IntArray &answer, const UnknownNumberingScheme &s)=0
int giveNumberOfContactDefinitions() const
std::vector< std::unique_ptr< GeneralBoundaryCondition > > & giveBcs()
Definition: domain.h:322
int giveNumberOfRows() const
Returns number of rows of receiver.
Definition: sparsemtrx.h:114
#define OOFEM_LOG_INFO(...)
Definition: logger.h:127
#define OOFEM_ERROR(...)
Definition: error.h:61
REGISTER_SparseMtrx(CompCol, SMT_CompCol)
void clear()
Clears the array (zero size).
Definition: intarray.h:177
virtual FloatArray * backSubstitutionWith(FloatArray &) const
Computes the solution of linear system where A is receiver.
Definition: skyline.C:289
int nwk
Total number of nonzero coefficients stored.
Definition: skyline.h:72
Abstract base class allowing to control the way, how equations are assigned to individual DOFs...
int setInternalStructure(IntArray &a)
Allocates and builds internal structure according to given array holding addresses of diagonal member...
Definition: skyline.C:338
int giveNumberOfNonZeros() const
Definition: skyline.h:148
virtual SparseMtrx * factorized()
Returns the receiver factorized.
Definition: skyline.C:499
double * mtrx
Vector of stored coefficients.
Definition: skyline.h:76
Abstract base class for all active boundary conditions.
Definition: activebc.h:63
virtual void add(double x, SparseMtrx &m)
Adds x * m.
Definition: skyline.C:633
double at(int i, int j) const
Coefficient access function.
Definition: floatmatrix.h:176
void resize(int n)
Checks size of receiver towards requested bounds.
Definition: intarray.C:124
This class manages all the contacts in a domain.
void rbmodes(FloatMatrix &r, int &nse, IntArray &se, double limit, int tc)
Splits the receiver to LDLT form, and computes the rigid body motions.
Definition: skyline.C:785
SparseMtrxVersionType version
Allows to track if receiver changes.
Definition: sparsemtrx.h:80
Initializes the variable VERBOSE, in order to get a few intermediate messages on screen: beginning an...
Class representing vector of real numbers.
Definition: floatarray.h:82
Implementation of matrix containing floating point numbers.
Definition: floatmatrix.h:94
virtual bool isDefault() const
Returns true, if receiver is the default engngModel equation numbering scheme; This is useful for som...
virtual int giveRequiredNumberOfDomainEquation() const
Returns required number of domain equation.
ContactManager * giveContactManager()
Definition: domain.C:393
void resize(int rows, int cols)
Checks size of receiver towards requested bounds.
Definition: floatmatrix.C:1358
ContactElement * giveContactElement(const int num)
void zero()
Zeroes all coefficients of receiver.
Definition: floatarray.C:658
Class implementing single timer, providing wall clock and user time capabilities. ...
Definition: timer.h:46
void printYourself() const
Prints matrix to stdout. Useful for debugging.
Definition: floatmatrix.C:1458
This class manages a particular contact definition.
void zero()
Zeroes all coefficient of receiver.
Definition: floatmatrix.C:1326
bool hasContactManager()
Definition: domain.C:404
int giveNumberOfColumns() const
Returns number of columns of receiver.
Definition: sparsemtrx.h:116
virtual void zero()
Zeroes the receiver.
Definition: skyline.C:669
ContactDefinition * giveContactDefinition(const int num)
int min(int i, int j)
Returns smaller value from two given decimals.
Definition: mathfem.h:59
std::vector< std::unique_ptr< Element > > & giveElements()
Definition: domain.h:279
Abstract base class representing the "problem" under consideration.
Definition: engngm.h:181
Skyline()
Constructor.
Definition: skyline.C:73
int giveSize() const
Definition: intarray.h:203
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
the oofem namespace is to define a context or scope in which all oofem names are defined.
Domain * giveDomain(int n)
Service for accessing particular problem domain.
Definition: engngm.C:1720
void clear()
Sets size of receiver to be an empty matrix. It will have zero rows and zero columns size...
Definition: floatmatrix.h:516
Symmetric skyline.
virtual int assemble(const IntArray &loc, const FloatMatrix &mat)
Assembles sparse matrix from contribution of local elements.
Definition: skyline.C:224
int giveNumberOfRows() const
Returns number of rows of receiver.
Definition: floatmatrix.h:156
void symmetrized()
Initializes the lower half of the receiver according to the upper half.
Definition: floatmatrix.C:1576
void startTimer()
Definition: timer.C:69
double getUtime()
Returns total user time elapsed in seconds.
Definition: timer.C:105
virtual ~Skyline()
Destructor.
Definition: skyline.C:83
void stopTimer()
Definition: timer.C:77
virtual void giveLocationArrays(std::vector< IntArray > &rows, std::vector< IntArray > &cols, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s)
Gives a list of location arrays that will be assembled.
Definition: activebc.h:138
virtual void printYourself() const
Prints receiver to stdout.
Definition: skyline.C:644
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