MAST
fem_operator_matrix.h
Go to the documentation of this file.
1 /*
2  * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
3  * Copyright (C) 2013-2019 Manav Bhatia
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #ifndef __mast__fem_operator_matrix__
21 #define __mast__fem_operator_matrix__
22 
23 // C++ includes
24 #include <vector>
25 #include <iomanip>
26 
27 // MAST includes
28 #include "base/mast_data_types.h"
29 
30 
31 
32 
33 namespace MAST {
34 
36  {
37  public:
39 
40 
41  virtual ~FEMOperatorMatrix();
42 
43 
47  void clear();
48 
49 
50  unsigned int m() const {return _n_interpolated_vars;}
51 
52  unsigned int n() const {return _n_discrete_vars*_n_dofs_per_var;}
53 
54  void print(std::ostream& o);
55 
62  void reinit(unsigned int n_interpolated_vars,
63  unsigned int n_discrete_vars,
64  unsigned int n_discrete_dofs_per_var);
65 
73  void set_shape_function(unsigned int interpolated_var,
74  unsigned int discrete_var,
75  const RealVectorX& shape_func);
76 
83  void reinit(unsigned int n_interpolated_vars,
84  const RealVectorX& shape_func);
85 
89  template <typename T>
90  void vector_mult(T& res, const T& v) const;
91 
92 
96  template <typename T>
97  void vector_mult_transpose(T& res, const T& v) const;
98 
99 
103  template <typename T>
104  void right_multiply(T& r, const T& m) const;
105 
106 
110  template <typename T>
111  void right_multiply_transpose(T& r, const T& m) const;
112 
113 
117  template <typename T>
118  void right_multiply_transpose(T& r, const MAST::FEMOperatorMatrix& m) const;
119 
120 
124  template <typename T>
125  void left_multiply(T& r, const T& m) const;
126 
127 
131  template <typename T>
132  void left_multiply_transpose(T& r, const T& m) const;
133 
134 
135  protected:
136 
140  unsigned int _n_interpolated_vars;
141 
145  unsigned int _n_discrete_vars;
146 
150  unsigned int _n_dofs_per_var;
151 
158  std::vector<RealVectorX*> _var_shape_functions;
159  };
160 
161 }
162 
163 
164 inline
165 void
167 
168  unsigned int index = 0;
169 
170  for (unsigned int i=0; i<_n_interpolated_vars; i++) {// row
171  for (unsigned int j=0; j<_n_discrete_vars; j++) { // column
172  index = j*_n_interpolated_vars+i;
173  if (_var_shape_functions[index]) // check if this is non-nullptr
174  for (unsigned int k=0; k<_n_dofs_per_var; k++)
175  o << std::setw(15) << (*_var_shape_functions[index])(k);
176  else
177  for (unsigned int k=0; k<_n_dofs_per_var; k++)
178  o << std::setw(15) << 0.;
179  }
180  o << std::endl;
181  }
182 }
183 
184 
185 inline
186 void
188 
190  _n_discrete_vars = 0;
191  _n_dofs_per_var = 0;
192 
193  // iterate over the shape function entries and delete the non-nullptr values
194  std::vector<RealVectorX*>::iterator it = _var_shape_functions.begin(),
195  end = _var_shape_functions.end();
196 
197  for ( ; it!=end; it++)
198  if ( *it != nullptr)
199  delete *it;
200 
201  _var_shape_functions.clear();
202 }
203 
204 
205 
206 
207 inline
208 void
210 reinit(unsigned int n_interpolated_vars,
211  unsigned int n_discrete_vars,
212  unsigned int n_discrete_dofs_per_var) {
213 
214  this->clear();
215  _n_interpolated_vars = n_interpolated_vars;
216  _n_discrete_vars = n_discrete_vars;
217  _n_dofs_per_var = n_discrete_dofs_per_var;
219  for (unsigned int i=0; i<_var_shape_functions.size(); i++)
220  _var_shape_functions[i] = nullptr;
221 }
222 
223 
224 
225 inline
226 void
228 set_shape_function(unsigned int interpolated_var,
229  unsigned int discrete_var,
230  const RealVectorX& shape_func) {
231 
232  // make sure that reinit has been called.
233  libmesh_assert(_var_shape_functions.size());
234 
235  // also make sure that the specified indices are within bounds
236  libmesh_assert(interpolated_var < _n_interpolated_vars);
237  libmesh_assert(discrete_var < _n_discrete_vars);
238 
239  RealVectorX* vec =
240  _var_shape_functions[discrete_var*_n_interpolated_vars+interpolated_var];
241 
242  if (!vec)
243  {
244  vec = new RealVectorX;
245  _var_shape_functions[discrete_var*_n_interpolated_vars+interpolated_var] = vec;
246  }
247 
248  *vec = shape_func;
249 }
250 
251 
252 
253 inline
254 void
256 reinit(unsigned int n_vars,
257  const RealVectorX& shape_func) {
258 
259  this->clear();
260 
261  _n_interpolated_vars = n_vars;
262  _n_discrete_vars = n_vars;
263  _n_dofs_per_var = (unsigned int)shape_func.size();
264  _var_shape_functions.resize(n_vars*n_vars);
265 
266  for (unsigned int i=0; i<n_vars; i++)
267  {
268  RealVectorX* vec = new RealVectorX;
269  *vec = shape_func;
270  _var_shape_functions[i*n_vars+i] = vec;
271  }
272 }
273 
274 
275 
276 template <typename T>
277 inline
278 void
280 vector_mult(T& res, const T& v) const {
281 
282  libmesh_assert_equal_to(res.size(), _n_interpolated_vars);
283  libmesh_assert_equal_to(v.size(), n());
284 
285  res.setZero();
286  unsigned int index = 0;
287 
288  for (unsigned int i=0; i<_n_interpolated_vars; i++) // row
289  for (unsigned int j=0; j<_n_discrete_vars; j++) { // column
290  index = j*_n_interpolated_vars+i;
291  if (_var_shape_functions[index]) // check if this is non-nullptr
292  for (unsigned int k=0; k<_n_dofs_per_var; k++)
293  res(i) +=
294  (*_var_shape_functions[index])(k) * v(j*_n_dofs_per_var+k);
295  }
296 }
297 
298 
299 template <typename T>
300 inline
301 void
303 vector_mult_transpose(T& res, const T& v) const {
304 
305  libmesh_assert_equal_to(res.size(), n());
306  libmesh_assert_equal_to(v.size(), _n_interpolated_vars);
307 
308  res.setZero(res.size());
309  unsigned int index = 0;
310 
311  for (unsigned int i=0; i<_n_interpolated_vars; i++) // row
312  for (unsigned int j=0; j<_n_discrete_vars; j++) { // column
313  index = j*_n_interpolated_vars+i;
314  if (_var_shape_functions[index]) // check if this is non-nullptr
315  for (unsigned int k=0; k<_n_dofs_per_var; k++)
316  res(j*_n_dofs_per_var+k) +=
317  (*_var_shape_functions[index])(k) * v(i);
318  }
319 }
320 
321 
322 
323 template <typename T>
324 inline
325 void
327 right_multiply(T& r, const T& m) const {
328 
329  libmesh_assert_equal_to(r.rows(), _n_interpolated_vars);
330  libmesh_assert_equal_to(r.cols(), m.cols());
331  libmesh_assert_equal_to(m.rows(), n());
332 
333  r.setZero();
334  unsigned int index = 0;
335 
336  for (unsigned int i=0; i<_n_interpolated_vars; i++) // row
337  for (unsigned int j=0; j<_n_discrete_vars; j++) { // column of operator
338  index = j*_n_interpolated_vars+i;
339  if (_var_shape_functions[index]) { // check if this is non-nullptr
340  for (unsigned int l=0; l<m.cols(); l++) // column of matrix
341  for (unsigned int k=0; k<_n_dofs_per_var; k++)
342  r(i,l) +=
343  (*_var_shape_functions[index])(k) * m(j*_n_dofs_per_var+k,l);
344  }
345  }
346 }
347 
348 
349 
350 
351 template <typename T>
352 inline
353 void
355 right_multiply_transpose(T& r, const T& m) const {
356 
357  libmesh_assert_equal_to(r.rows(), n());
358  libmesh_assert_equal_to(r.cols(), m.cols());
359  libmesh_assert_equal_to(m.rows(), _n_interpolated_vars);
360 
361  r.setZero(r.rows(), r.cols());
362  unsigned int index = 0;
363 
364  for (unsigned int i=0; i<_n_interpolated_vars; i++) // row
365  for (unsigned int j=0; j<_n_discrete_vars; j++) { // column of operator
366  index = j*_n_interpolated_vars+i;
367  if (_var_shape_functions[index]) { // check if this is non-nullptr
368  for (unsigned int l=0; l<m.cols(); l++) // column of matrix
369  for (unsigned int k=0; k<_n_dofs_per_var; k++)
370  r(j*_n_dofs_per_var+k,l) +=
371  (*_var_shape_functions[index])(k) * m(i,l);
372  }
373  }
374 }
375 
376 
377 
378 template <typename T>
379 inline
380 void
383 
384  libmesh_assert_equal_to(r.rows(), n());
385  libmesh_assert_equal_to(r.cols(), m.n());
386  libmesh_assert_equal_to(_n_interpolated_vars, m._n_interpolated_vars);
387 
388  r.setZero();
389  unsigned int index_i, index_j = 0;
390 
391  for (unsigned int i=0; i<_n_discrete_vars; i++) // row of result
392  for (unsigned int j=0; j<m._n_discrete_vars; j++) // column of result
393  for (unsigned int k=0; k<_n_interpolated_vars; k++) {
394  index_i = i*_n_interpolated_vars+k;
395  index_j = j*m._n_interpolated_vars+k;
396  if (_var_shape_functions[index_i] &&
397  m._var_shape_functions[index_j]) { // if shape function exists for both
398  const RealVectorX &n1 = *_var_shape_functions[index_i],
399  &n2 = *m._var_shape_functions[index_j];
400  for (unsigned int i_n1=0; i_n1<n1.size(); i_n1++)
401  for (unsigned int i_n2=0; i_n2<n2.size(); i_n2++)
402  r (i*_n_dofs_per_var+i_n1,
403  j*m._n_dofs_per_var+i_n2) += n1(i_n1) * n2(i_n2);
404  }
405  }
406 }
407 
408 
409 
410 
411 template <typename T>
412 inline
413 void
415 left_multiply(T& r, const T& m) const {
416 
417  libmesh_assert_equal_to(r.rows(), m.rows());
418  libmesh_assert_equal_to(r.cols(), n());
419  libmesh_assert_equal_to(m.cols(), _n_interpolated_vars);
420 
421  r.setZero(r.rows(), r.cols());
422  unsigned int index = 0;
423 
424  for (unsigned int i=0; i<_n_interpolated_vars; i++) // row
425  for (unsigned int j=0; j<_n_discrete_vars; j++) { // column of operator
426  index = j*_n_interpolated_vars+i;
427  if (_var_shape_functions[index]) { // check if this is non-nullptr
428  for (unsigned int l=0; l<m.rows(); l++) // rows of matrix
429  for (unsigned int k=0; k<_n_dofs_per_var; k++)
430  r(l,j*_n_dofs_per_var+k) +=
431  (*_var_shape_functions[index])(k) * m(l,i);
432  }
433  }
434 }
435 
436 
437 
438 template <typename T>
439 inline
440 void
442 left_multiply_transpose(T& r, const T& m) const {
443 
444  libmesh_assert_equal_to(r.rows(), m.rows());
445  libmesh_assert_equal_to(r.cols(), _n_interpolated_vars);
446  libmesh_assert_equal_to(m.cols(), n());
447 
448  r.setZero();
449  unsigned int index = 0;
450 
451  for (unsigned int i=0; i<_n_interpolated_vars; i++) // row
452  for (unsigned int j=0; j<_n_discrete_vars; j++) { // column of operator
453  index = j*_n_interpolated_vars+i;
454  if (_var_shape_functions[index]) { // check if this is non-nullptr
455  for (unsigned int l=0; l<m.rows(); l++) // column of matrix
456  for (unsigned int k=0; k<_n_dofs_per_var; k++)
457  r(l,i) +=
458  (*_var_shape_functions[index])(k) * m(l,j*_n_dofs_per_var+k);
459  }
460  }
461 }
462 
463 
464 
465 
466 #endif // __mast__fem_operator_matrix__
467 
void vector_mult_transpose(T &res, const T &v) const
res = v^T * [this]
void reinit(unsigned int n_interpolated_vars, unsigned int n_discrete_vars, unsigned int n_discrete_dofs_per_var)
this initializes the operator for number of rows and variables, assuming that all variables has the s...
void set_shape_function(unsigned int interpolated_var, unsigned int discrete_var, const RealVectorX &shape_func)
sets the shape function values for the block corresponding to interpolated_var and discrete_var...
void right_multiply(T &r, const T &m) const
[R] = [this] * [M]
void clear()
clears the data structures
unsigned int m() const
std::vector< RealVectorX * > _var_shape_functions
stores the shape function values that defines the coupling of i_th interpolated var and j_th discrete...
unsigned int n() const
unsigned int _n_discrete_vars
number of discrete variables in the system
unsigned int _n_dofs_per_var
number of dofs for each variable
void print(std::ostream &o)
void vector_mult(T &res, const T &v) const
res = [this] * v
void left_multiply_transpose(T &r, const T &m) const
[R] = [M] * [this]^T
Matrix< Real, Dynamic, 1 > RealVectorX
void right_multiply_transpose(T &r, const T &m) const
[R] = [this]^T * [M]
void left_multiply(T &r, const T &m) const
[R] = [M] * [this]
unsigned int _n_interpolated_vars
number of rows of the operator