Flow123d  JS_before_hm-937-g93502c2
local_system.cc
Go to the documentation of this file.
1 
2 #include "local_system.hh"
3 
4 #include <armadillo>
5 #include "system/asserts.hh"
6 #include "system/index_types.hh"
7 
8 
10 {}
11 
12 
14 : row_dofs(nrows),
15  col_dofs(ncols),
16  matrix(nrows, ncols),
17  rhs(nrows),
18  sparsity(nrows,ncols),
19  elim_rows(nrows),
20  elim_cols(ncols),
21  solution_rows(nrows),
22  solution_cols(ncols),
23  diag_rows(nrows)
24 {
25  reset();
26 }
27 
28 void LocalSystem::set_size(uint nrows, uint ncols)
29 {
30  row_dofs.set_size(nrows);
31  col_dofs.set_size(ncols);
32  matrix.set_size(nrows, ncols);
33  rhs.set_size(nrows);
34  elim_rows.set_size(nrows);
35  elim_cols.set_size(ncols);
36  solution_rows.set_size(nrows);
37  solution_cols.set_size(ncols);
38  diag_rows.set_size(nrows);
39  // destroy previous sparsity pattern
40  sparsity.set_size(nrows,ncols);
41  sparsity.fill(almost_zero);
42 }
43 
44 
46 {
47  // zeros in local system
48  matrix.zeros();
49  rhs.zeros();
50  // drop all dirichlet values
52 }
53 
54 
55 void LocalSystem::reset(uint nrows, uint ncols)
56 {
57  if(matrix.n_rows != nrows || matrix.n_cols != ncols)
58  {
59  set_size(nrows, ncols);
60  }
61 
62  reset();
63 }
64 
65 
66 
67 void LocalSystem::reset(const LocDofVec &rdofs, const LocDofVec &cdofs)
68 {
69  if(matrix.n_rows != rdofs.n_rows || matrix.n_cols != cdofs.n_rows)
70  {
71  set_size(rdofs.n_rows, cdofs.n_rows);
72  }
73 
74  reset();
75  row_dofs = rdofs;
76  col_dofs = cdofs;
77 }
78 
79 
80 
81 void LocalSystem::set_solution(uint loc_dof, double solution, double diag)
82 {
83  // check that dofs are same
84  //ASSERT_DBG( arma::all(row_dofs == col_dofs) );
85  set_solution_row(loc_dof, solution, diag);
86  set_solution_col(loc_dof, solution);
87 }
88 
89 void LocalSystem::set_solution_row(uint loc_row, double solution, double diag) {
90  elim_rows[n_elim_rows]=loc_row;
91  solution_rows[n_elim_rows] = solution;
92  diag_rows[n_elim_rows] = diag;
93  n_elim_rows++;
94 }
95 
96 void LocalSystem::set_solution_col(uint loc_col, double solution) {
97  elim_cols[n_elim_cols]=loc_col;
98  solution_cols[n_elim_cols] = solution;
99  n_elim_cols++;
100 }
101 
103 {
104  //if there is solution set, eliminate:
105  if (n_elim_rows || n_elim_cols )
106  {
107  //DebugOut().fmt("elim rows: {} elim_cols: {}", n_elim_rows, n_elim_cols);
108 
109  arma::mat tmp_mat = matrix;
110  arma::vec tmp_rhs = rhs;
111 
112  uint ic, ir, row, col;
113 
114  // eliminate columns
115  for(ic=0; ic < n_elim_cols; ic++) {
116  col = elim_cols[ic];
117  tmp_rhs -= solution_cols[ic] * tmp_mat.col( col );
118  tmp_mat.col( col ).zeros();
119  }
120 
121  // eliminate rows
122  for(ir=0; ir < n_elim_rows; ir++) {
123  row = elim_rows[ir];
124  tmp_rhs( row ) = 0.0;
125  tmp_mat.row( row ).zeros();
126 
127  // fix global diagonal
128  for(ic=0; ic < n_elim_cols; ic++) {
129  col = elim_cols[ic];
130  if (row_dofs[row] == col_dofs[col]) {
131  ASSERT_DBG(fabs(solution_rows[ir] - solution_cols[ic]) <1e-12 );
132  // if preferred value is not set, then try using matrix value
133  double new_diagonal = matrix(row, col);
134 
135  if (diag_rows[ir] != 0.0) // if preferred value is set
136  new_diagonal = diag_rows[ir];
137  else if(new_diagonal == 0.0) // if an assembled value is not available
138  new_diagonal = 1.0;
139  // double new_diagonal = fabs(matrix(sol_row,col));
140  // if (new_diagonal == 0.0) {
141  // if (matrix.is_square()) {
142  // new_diagonal = arma::sum( abs(matrix.diag())) / matrix.n_rows;
143  // } else {
144  // new_diagonal = arma::accu( abs(matrix) ) / matrix.n_elem;
145  // }
146  // }
147  tmp_mat(row,col) = new_diagonal;
148  tmp_rhs(row) = new_diagonal * solution_rows[ir];
149 
150  }
151  }
152  }
153 
154  matrix = tmp_mat;
155  rhs = tmp_rhs;
156  n_elim_cols=n_elim_rows=0;
157  }
158 
159  // filling almost_zero according to sparsity pattern
160  ASSERT_EQ_DBG(matrix.n_rows, sparsity.n_rows);
161  ASSERT_EQ_DBG(matrix.n_cols, sparsity.n_cols);
162  matrix = matrix + sparsity;
163 
164  //DebugOut() << matrix;
165  //DebugOut() << rhs;
166 }
167 
168 
169 void LocalSystem::add_value(uint row, uint col, double mat_val, double rhs_val)
170 {
171  ASSERT_DBG(row < matrix.n_rows);
172  ASSERT_DBG(col < matrix.n_cols);
173  ASSERT_DBG(sparsity(row,col))(row)(col).error("Violation of sparsity pattern.");
174 
175  matrix(row, col) += mat_val;
176  rhs(row) += rhs_val;
177 }
178 
179 void LocalSystem::add_value(uint row, uint col, double mat_val)
180 {
181  ASSERT_DBG(row < matrix.n_rows);
182  ASSERT_DBG(col < matrix.n_cols);
183  ASSERT_DBG(sparsity(row,col))(row)(col).error("Violation of sparsity pattern.");
184 
185  matrix(row, col) += mat_val;
186 }
187 
188 void LocalSystem::add_value(uint row, double rhs_val)
189 {
190  ASSERT_DBG(row < matrix.n_rows);
191 
192  rhs(row) += rhs_val;
193 }
194 
195 
197  ASSERT_EQ_DBG(matrix.n_rows, m.n_rows);
198  ASSERT_EQ_DBG(matrix.n_cols, m.n_cols);
199  matrix = m;
200 }
201 
203  ASSERT_EQ_DBG(matrix.n_rows, r.n_rows);
204  rhs = r;
205 }
206 
207 void LocalSystem::set_sparsity(const arma::umat & sp)
208 {
209  ASSERT_EQ_DBG(sparsity.n_rows, sp.n_rows);
210  ASSERT_EQ_DBG(sparsity.n_cols, sp.n_cols);
211 
212  sparsity.zeros();
213  for(uint i=0; i < sp.n_rows; i++)
214  for(uint j=0; j < sp.n_cols; j++)
215  if( sp(i,j) != 0 )
216  sparsity(i,j) = almost_zero;
217 // sparsity.print("sparsity");
218 }
219 
221 {
222  // only for square matrix
223  ASSERT_EQ_DBG(matrix.n_rows, matrix.n_cols)("Cannot compute Schur complement for non-square matrix.");
224  arma::uword n = matrix.n_rows - 1;
225  ASSERT_LT_DBG(offset, n)("Schur complement (offset) dimension mismatch.");
226 
227  // B * invA
228  arma::mat BinvA = matrix.submat(offset, 0, n, offset-1) * matrix.submat(0, 0, offset-1, offset-1).i();
229 
230  // Schur complement S = C - B * invA * Bt
231  schur.matrix = matrix.submat(offset, offset, n, n) - BinvA * matrix.submat(0, offset, offset-1, n);
232  schur.rhs = rhs.subvec(offset, n) - BinvA * rhs.subvec(0, offset-1);
233 
234  if(negative)
235  {
236  schur.matrix = -1.0 * schur.matrix;
237  schur.rhs = -1.0 * schur.rhs;
238  }
239 }
240 
241 void LocalSystem::reconstruct_solution_schur(uint offset, const arma::vec &schur_solution, arma::vec& reconstructed_solution) const
242 {
243  // only for square matrix
244  ASSERT_EQ_DBG(matrix.n_rows, matrix.n_cols)("Cannot compute Schur complement for non-square matrix.");
245  arma::uword n = matrix.n_rows - 1;
246  ASSERT_LT_DBG(offset, n)("Schur complement (offset) dimension mismatch.");
247 
248  reconstructed_solution.set_size(offset);
249  // invA
250  arma::mat invA = matrix.submat(0, 0, offset-1, offset-1).i();
251 
252  // x = invA*b - invA * Bt * schur_solution
253  reconstructed_solution = invA * rhs.subvec(0,offset-1) - invA * matrix.submat(0, offset, offset-1, n) * schur_solution;
254 }
LocDofVec row_dofs
Definition: local_system.hh:53
void set_solution_col(uint loc_col, double solution)
Definition: local_system.cc:96
#define ASSERT_EQ_DBG(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:332
ArmaVec< double, N > vec
Definition: armor.hh:861
arma::Col< IntIdx > LocDofVec
Definition: index_types.hh:28
unsigned int uint
void set_matrix(arma::mat matrix)
void compute_schur_complement(uint offset, LocalSystem &schur, bool negative=false) const
Computes Schur complement of the local system: S = C - B * invA * Bt Applicable for square matrices...
void set_sparsity(const arma::umat &sp)
Sets the sparsity pattern for the local system.
LocDofVec elim_rows
static constexpr double almost_zero
Prefered values on the diagonal after elimination.
Definitions of ASSERTS.
LocDofVec elim_cols
Rows indices of rows to be eliminated.
arma::vec rhs
local system RHS
arma::vec solution_rows
Cols indices of cols to be eliminated.
void add_value(uint row, uint col, double mat_val, double rhs_val)
Adds a single entry into the local system.
LocDofVec col_dofs
Definition: local_system.hh:53
ArmaMat< double, N, M > mat
Definition: armor.hh:864
arma::mat sparsity
sparsity pattern
void reset()
Resets the matrix, RHS, dofs to zero and clears solution settings.
Definition: local_system.cc:45
void set_size(uint nrows, uint ncols)
Definition: local_system.cc:28
arma::vec diag_rows
Values of the known solution (for col dofs).
LocalSystem()
Default constructor.
Definition: local_system.cc:9
arma::mat matrix
local system matrix
void reconstruct_solution_schur(uint offset, const arma::vec &schur_solution, arma::vec &reconstructed_solution) const
Reconstructs the solution from the Schur complement solution: x = invA*b - invA * Bt * schur_solution...
void set_solution_row(uint loc_row, double solution, double diag=0.0)
Definition: local_system.cc:89
void set_rhs(arma::vec rhs)
#define ASSERT_DBG(expr)
arma::vec solution_cols
Values of the known solution (for row dofs).
uint n_elim_rows
Number of rows/cols to be eliminated due to known solution.
void eliminate_solution()
void set_solution(uint loc_dof, double solution, double diag=0.0)
Set the position and value of known solution. E.g. Dirichlet boundary condition.
Definition: local_system.cc:81
#define ASSERT_LT_DBG(a, b)
Definition of comparative assert macro (Less Than) only for debug mode.
Definition: asserts.hh:300