MAST3
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
fem_operator_matrix.hpp
Go to the documentation of this file.
1 /*
2  * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
3  * Copyright (C) 2013-2020 Manav Bhatia and MAST authors
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_h__
21 #define __mast__fem_operator_matrix_h__
22 
23 // C++ includes
24 #include <vector>
25 #include <iomanip>
26 
27 // MAST includes
29 #include <mast/base/exceptions.hpp>
30 
31 
32 
33 namespace MAST {
34 namespace Numerics {
35 
36 template <typename ScalarType>
38 {
39 public:
41 
42 
43  virtual ~FEMOperatorMatrix();
44 
45 
49  void clear();
50 
51 
52  uint_t m() const {return _n_interpolated_vars;}
53 
55 
56  void print(std::ostream& o);
57 
64  inline void reinit(uint_t n_interpolated_vars,
65  uint_t n_discrete_vars,
66  uint_t n_discrete_dofs_per_var);
67 
75  template <typename VecType>
76  inline void set_shape_function(uint_t interpolated_var,
77  uint_t discrete_var,
78  const VecType& shape_func);
79 
80  template <typename VecType>
81  inline void
82  set_shape_function(uint_t interpolated_var,
83  uint_t discrete_var,
84  const ScalarType v,
85  const VecType& shape_func);
92  template <typename VecType>
93  inline void reinit(uint_t n_interpolated_vars,
94  const VecType& shape_func);
95 
99  template <typename T>
100  inline void vector_mult(T& res, const T& v) const;
101 
102 
106  template <typename T1, typename T2>
107  inline void vector_mult_transpose(T1& res, const T2& v) const;
108 
109 
113  template <typename T>
114  inline void right_multiply(T& r, const T& m) const;
115 
116 
120  template <typename T>
121  inline void right_multiply_transpose(T& r, const T& m) const;
122 
123 
127  template <typename T>
128  inline void right_multiply_transpose
129  (T& r,
131 
132 
136  template <typename T1, typename T2>
137  inline void left_multiply(T1& r, const T2& m) const;
138 
139 
143  template <typename T>
144  inline void left_multiply_transpose(T& r, const T& m) const;
145 
146 
147 protected:
148 
153 
158 
163 
170  std::vector<ScalarType*> _var_shape_functions;
171 };
172 
173 } // namespace Numerics
174 } // namespace MAST
175 
176 template <typename ScalarType>
181 {
182 
183 }
184 
185 
186 template <typename ScalarType>
188 {
189  this->clear();
190 }
191 
192 
193 template <typename ScalarType>
194 inline
195 void
197 
198  uint_t index = 0;
199 
200  for (uint_t i=0; i<_n_interpolated_vars; i++) {// row
201  for (uint_t j=0; j<_n_discrete_vars; j++) { // column
202  index = j*_n_interpolated_vars+i;
203  if (_var_shape_functions[index]) // check if this is non-nullptr
204  for (uint_t k=0; k<_n_dofs_per_var; k++)
205  o << std::setw(15) << _var_shape_functions[index][k];
206  else
207  for (uint_t k=0; k<_n_dofs_per_var; k++)
208  o << std::setw(15) << 0.;
209  }
210  o << std::endl;
211  }
212 }
213 
214 
215 template <typename ScalarType>
216 inline
217 void
219 
221  _n_discrete_vars = 0;
222  _n_dofs_per_var = 0;
223 
224  // iterate over the shape function entries and delete the non-nullptr values
225  typename std::vector<ScalarType*>::iterator
226  it = _var_shape_functions.begin(),
227  end = _var_shape_functions.end();
228 
229  for ( ; it!=end; it++)
230  if ( *it != nullptr)
231  delete *it;
232 
233  _var_shape_functions.clear();
234 }
235 
236 
237 
238 
239 template <typename ScalarType>
240 inline
241 void
243 reinit(uint_t n_interpolated_vars,
244  uint_t n_discrete_vars,
245  uint_t n_discrete_dofs_per_var) {
246 
247  this->clear();
248  _n_interpolated_vars = n_interpolated_vars;
249  _n_discrete_vars = n_discrete_vars;
250  _n_dofs_per_var = n_discrete_dofs_per_var;
252 }
253 
254 
255 
256 template <typename ScalarType>
257 template <typename VecType>
258 inline
259 void
261 set_shape_function(uint_t interpolated_var,
262  uint_t discrete_var,
263  const VecType& shape_func) {
264 
265  // make sure that reinit has been called.
266  Assert0(_var_shape_functions.size(), "Object not initialized");
267 
268  // also make sure that the specified indices are within bounds
269  Assert2(interpolated_var < _n_interpolated_vars,
270  interpolated_var, _n_interpolated_vars,
271  "Invalid interpolation variable index");
272  Assert2(discrete_var < _n_discrete_vars,
273  discrete_var, _n_discrete_vars,
274  "Invalid discrete variable index");
275  Assert2(shape_func.size() == _n_dofs_per_var,
276  shape_func.size(), _n_dofs_per_var,
277  "Invalid basis function vector size.");
278 
279  ScalarType* vec =
280  _var_shape_functions[discrete_var*_n_interpolated_vars+interpolated_var];
281 
282  if (!vec) {
283 
284  vec = new ScalarType[shape_func.size()];
285  _var_shape_functions[discrete_var*_n_interpolated_vars+interpolated_var] = vec;
286  }
287 
288  for (uint_t i=0; i<_n_dofs_per_var; i++)
289  vec[i] = shape_func(i);
290 }
291 
292 
293 
294 template <typename ScalarType>
295 template <typename VecType>
296 inline
297 void
299 set_shape_function(uint_t interpolated_var,
300  uint_t discrete_var,
301  const ScalarType v,
302  const VecType& shape_func) {
303 
304  // make sure that reinit has been called.
305  Assert0(_var_shape_functions.size(), "Object not initialized");
306 
307  // also make sure that the specified indices are within bounds
308  Assert2(interpolated_var < _n_interpolated_vars,
309  interpolated_var, _n_interpolated_vars,
310  "Invalid interpolation variable index");
311  Assert2(discrete_var < _n_discrete_vars,
312  discrete_var, _n_discrete_vars,
313  "Invalid discrete variable index");
314  Assert2(shape_func.size() == _n_dofs_per_var,
315  shape_func.size(), _n_dofs_per_var,
316  "Invalid basis function vector size.");
317 
318  ScalarType* vec =
319  _var_shape_functions[discrete_var*_n_interpolated_vars+interpolated_var];
320 
321  if (!vec) {
322 
323  vec = new ScalarType[shape_func.size()];
324  _var_shape_functions[discrete_var*_n_interpolated_vars+interpolated_var] = vec;
325  }
326 
327  for (uint_t i=0; i<_n_dofs_per_var; i++)
328  vec[i] = v*shape_func(i);
329 }
330 
331 
332 
333 
334 template <typename ScalarType>
335 template <typename VecType>
336 inline
337 void
339 reinit(uint_t n_vars,
340  const VecType& shape_func) {
341 
342  this->clear();
343 
344  _n_interpolated_vars = n_vars;
345  _n_discrete_vars = n_vars;
346  _n_dofs_per_var = (uint_t)shape_func.size();
347  _var_shape_functions.resize(n_vars*n_vars, nullptr);
348 
349  for (uint_t i=0; i<n_vars; i++)
350  {
351  ScalarType *vec = new ScalarType[_n_dofs_per_var];
352  for (uint_t i=0; i<_n_dofs_per_var; i++)
353  vec[i] = shape_func(i);
354  _var_shape_functions[i*n_vars+i] = vec;
355  }
356 }
357 
358 
359 
360 template <typename ScalarType>
361 template <typename T>
362 inline
363 void
365 vector_mult(T& res, const T& v) const {
366 
367  Assert2(res.size() == _n_interpolated_vars,
368  res.size(), _n_interpolated_vars,
369  "Incompatible vector size.");
370  Assert2(v.size() == n(),
371  v.size(), n(),
372  "Incompatible vector size");
373 
374  res.setZero();
375  uint_t index = 0;
376 
377  for (uint_t i=0; i<_n_interpolated_vars; i++) // row
378  for (uint_t j=0; j<_n_discrete_vars; j++) { // column
379  index = j*_n_interpolated_vars+i;
380  if (_var_shape_functions[index]) // check if this is non-nullptr
381  for (uint_t k=0; k<_n_dofs_per_var; k++)
382  res(i) +=
383  _var_shape_functions[index][k] * v(j*_n_dofs_per_var+k);
384  }
385 }
386 
387 template <typename ScalarType>
388 template <typename T1, typename T2>
389 inline
390 void
392 vector_mult_transpose(T1& res, const T2& v) const {
393 
394  Assert2(res.size() == n(),
395  res.size(), n(),
396  "Incompatible vector size");
397  Assert2(v.size() == _n_interpolated_vars,
398  v.size(), _n_interpolated_vars,
399  "Incompatible vector size");
400 
401  res.setZero(res.size());
402  uint_t index = 0;
403 
404  for (uint_t i=0; i<_n_interpolated_vars; i++) // row
405  for (uint_t j=0; j<_n_discrete_vars; j++) { // column
406  index = j*_n_interpolated_vars+i;
407  if (_var_shape_functions[index]) // check if this is non-nullptr
408  for (uint_t k=0; k<_n_dofs_per_var; k++)
409  res(j*_n_dofs_per_var+k) +=
410  _var_shape_functions[index][k] * v(i);
411  }
412 }
413 
414 
415 
416 template <typename ScalarType>
417 template <typename T>
418 inline
419 void
421 right_multiply(T& r, const T& m) const {
422 
423  Assert2(r.rows() == _n_interpolated_vars,
424  r.rows(), _n_interpolated_vars,
425  "Incompatible matrix row dimension");
426  Assert2(r.cols() == m.cols(),
427  r.cols(), m.cols(),
428  "Incompatible matrix column dimension");
429  Assert2(m.rows() == n(),
430  m.rows(), n(),
431  "Incompatible matrix row dimension");
432 
433  r.setZero();
434  uint_t index = 0;
435 
436  for (uint_t i=0; i<_n_interpolated_vars; i++) // row
437  for (uint_t j=0; j<_n_discrete_vars; j++) { // column of operator
438  index = j*_n_interpolated_vars+i;
439  if (_var_shape_functions[index]) { // check if this is non-nullptr
440  for (uint_t l=0; l<m.cols(); l++) // column of matrix
441  for (uint_t k=0; k<_n_dofs_per_var; k++)
442  r(i,l) +=
443  _var_shape_functions[index][k] * m(j*_n_dofs_per_var+k,l);
444  }
445  }
446 }
447 
448 
449 
450 
451 template <typename ScalarType>
452 template <typename T>
453 inline
454 void
456 right_multiply_transpose(T& r, const T& m) const {
457 
458  Assert2(r.rows() == n(),
459  r.rows(), n(),
460  "Incompatible matrix row dimension");
461  Assert2(r.cols() == m.cols(),
462  r.cols(), m.cols(),
463  "Incompatible matrix column dimension");
464  Assert2(m.rows() == _n_interpolated_vars,
465  m.rows(), _n_interpolated_vars,
466  "Incompatible matrix row dimension");
467 
468  r.setZero(r.rows(), r.cols());
469  uint_t index = 0;
470 
471  for (uint_t i=0; i<_n_interpolated_vars; i++) // row
472  for (uint_t j=0; j<_n_discrete_vars; j++) { // column of operator
473  index = j*_n_interpolated_vars+i;
474  if (_var_shape_functions[index]) { // check if this is non-nullptr
475  for (uint_t l=0; l<m.cols(); l++) // column of matrix
476  for (uint_t k=0; k<_n_dofs_per_var; k++)
477  r(j*_n_dofs_per_var+k,l) +=
478  _var_shape_functions[index][k] * m(i,l);
479  }
480  }
481 }
482 
483 
484 
485 template <typename ScalarType>
486 template <typename T>
487 inline
488 void
491 
492  Assert2(r.rows() == n(),
493  r.rows(), n(),
494  "Incompatible matrix row dimension");
495  Assert2(r.cols() == m.n(),
496  r.cols(), m.n(),
497  "Incompatible matrix column dimension");
500  "Incompatible number of variables");
501 
502  r.setZero();
503  uint_t index_i, index_j = 0;
504 
505  for (uint_t i=0; i<_n_discrete_vars; i++) // row of result
506  for (uint_t j=0; j<m._n_discrete_vars; j++) // column of result
507  for (uint_t k=0; k<_n_interpolated_vars; k++) {// same number of interpolated vars in both
508  index_i = i*_n_interpolated_vars+k; // column major index of shape function
509  index_j = j*m._n_interpolated_vars+k;
510  if (_var_shape_functions[index_i] &&
511  m._var_shape_functions[index_j]) { // if shape function exists for both
512  const ScalarType
513  *n1 = _var_shape_functions[index_i],
514  *n2 = m._var_shape_functions[index_j];
515  for (uint_t i_n1=0; i_n1<_n_dofs_per_var; i_n1++)
516  for (uint_t i_n2=0; i_n2<m._n_dofs_per_var; i_n2++)
517  r (i*_n_dofs_per_var+i_n1,
518  j*m._n_dofs_per_var+i_n2) += n1[i_n1] * n2[i_n2];
519  }
520  }
521 }
522 
523 
524 
525 
526 template <typename ScalarType>
527 template <typename T1, typename T2>
528 inline
529 void
531 left_multiply(T1& r, const T2& m) const {
532 
533  Assert2(r.rows() == m.rows(),
534  r.rows(), m.rows(),
535  "Incompatible matrix rows");
536  Assert2(r.cols() == n(),
537  r.cols(), n(),
538  "Incompatible matrix columns");
539  Assert2(m.cols() == _n_interpolated_vars,
540  m.cols(), _n_interpolated_vars,
541  "Incompatible matrix columns");
542 
543  r.setZero(r.rows(), r.cols());
544  uint_t index = 0;
545 
546  for (uint_t i=0; i<_n_interpolated_vars; i++) // row
547  for (uint_t j=0; j<_n_discrete_vars; j++) { // column of operator
548  index = j*_n_interpolated_vars+i;
549  if (_var_shape_functions[index]) { // check if this is non-nullptr
550  for (uint_t l=0; l<m.rows(); l++) // rows of matrix
551  for (uint_t k=0; k<_n_dofs_per_var; k++)
552  r(l,j*_n_dofs_per_var+k) +=
553  _var_shape_functions[index][k] * m(l,i);
554  }
555  }
556 }
557 
558 
559 
560 template <typename ScalarType>
561 template <typename T>
562 inline
563 void
565 left_multiply_transpose(T& r, const T& m) const {
566 
567  Assert2(r.rows() == m.rows(),
568  r.rows(), m.rows(),
569  "Incompatible matrix rows");
570  Assert2(r.cols() == _n_interpolated_vars,
571  r.cols(), _n_interpolated_vars,
572  "Incompatible matrix columns");
573  Assert2(m.cols() == n(),
574  m.cols(), n(),
575  "Incompatible matrix columns");
576 
577  r.setZero();
578  uint_t index = 0;
579 
580  for (uint_t i=0; i<_n_interpolated_vars; i++) // row
581  for (uint_t j=0; j<_n_discrete_vars; j++) { // column of operator
582  index = j*_n_interpolated_vars+i;
583  if (_var_shape_functions[index]) { // check if this is non-nullptr
584  for (uint_t l=0; l<m.rows(); l++) // column of matrix
585  for (uint_t k=0; k<_n_dofs_per_var; k++)
586  r(l,i) +=
587  _var_shape_functions[index][k] * m(l,j*_n_dofs_per_var+k);
588  }
589  }
590 }
591 
592 
593 
594 #endif // __mast__fem_operator_matrix_h__
595 
void left_multiply_transpose(T &r, const T &m) const
[R] = [M] * [this]^T
void right_multiply(T &r, const T &m) const
[R] = [this] * [M]
void vector_mult_transpose(T1 &res, const T2 &v) const
res = v^T * [this]
void clear()
clears the data structures
uint_t _n_dofs_per_var
number of dofs for each variable
uint_t _n_interpolated_vars
number of rows of the operator
void right_multiply_transpose(T &r, const T &m) const
[R] = [this]^T * [M]
void left_multiply(T1 &r, const T2 &m) const
[R] = [M] * [this]
std::vector< ScalarType * > _var_shape_functions
stores the shape function values that defines the coupling of i_th interpolated var and j_th discrete...
void vector_mult(T &res, const T &v) const
res = [this] * v
#define Assert0(cond, msg)
Definition: exceptions.hpp:134
void set_shape_function(uint_t interpolated_var, uint_t discrete_var, const VecType &shape_func)
sets the shape function values for the block corresponding to interpolated_var and discrete_var...
unsigned int uint_t
#define Assert2(cond, v1, v2, msg)
Definition: exceptions.hpp:152
void reinit(uint_t n_interpolated_vars, uint_t n_discrete_vars, uint_t n_discrete_dofs_per_var)
this initializes the operator for number of rows and variables, assuming that all variables has the s...
uint_t _n_discrete_vars
number of discrete variables in the system