OOFEM 3.0
Loading...
Searching...
No Matches
floatmatrixf.h
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 - 2025 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#pragma once
36
37#ifndef floatmatrixf_h
38#define floatmatrixf_h
39
40#include "oofemenv.h"
41#include "contextioresulttype.h"
42#include "contextmode.h"
43#include "floatmatrix.h"
44#include "floatarrayf.h"
45
46#include <array>
47#include <initializer_list>
48#include <algorithm>
49#include <utility>
50#include <iosfwd>
51
52namespace oofem {
53
54
55#define _LOOP_FLOATMATRIX(M,r,c) for(std::size_t c=0; c<M.cols(); c++) for(std::size_t r=0; r<M.rows(); r++)
56
61template<std::size_t N, std::size_t M>
63#ifdef _USE_EIGEN
64: public MatrixRCd<N,M>
65#endif
66{
67#ifdef _USE_EIGEN
68public:
69 typedef MatrixRCd<N,M> MatrixRCd_NM;
70 OOFEM_EIGEN_DERIVED(FloatMatrixF,MatrixRCd_NM);
71 const double *data() const { return MatrixRCd_NM::data(); }
72 double *data() { return MatrixRCd_NM::data(); }
73 template<
74 typename... Args,
75 class = typename std::enable_if_t<sizeof...(Args) == M*N>,
76 class = std::enable_if_t<(std::conjunction_v<std::is_same<double, Args>...>)>
77 >
78 FloatMatrixF(Args... args) {
79 std::initializer_list<double> ini{ args ... };
80 assert(ini.size()==rows()*cols());
81 int i=0;
82 for(const double& x: ini){
83 (*this)(i%rows(),i/rows())=x;
84 i++;
85 }
86 }
87 // redefine because of signedness (move to Index in the future pehaps)
88 std::size_t rows() const{ return MatrixRCd_NM::rows(); }
89 std::size_t cols() const{ return MatrixRCd_NM::cols(); }
90#else
91protected:
93 std::array< double, N*M > values;
94public:
99 template< typename... V, class = typename std::enable_if_t<sizeof...(V) == N*M> >
100 FloatMatrixF(V... x) noexcept : values{x...} { }
104 FloatMatrixF() noexcept : values{} { }
106 FloatMatrixF(const FloatMatrixF<N,M> &mat) noexcept : values(mat.values) {}
109 {
110 #ifndef NDEBUG
111 if ( mat.rows() != N || mat.cols() != M ) {
112 throw std::out_of_range("Can't convert dynamic float matrix of size " +
113 std::to_string(mat.rows()) + "x" + std::to_string(mat.cols()) +
114 " to fixed size " + std::to_string(N) + "x" + std::to_string(M));
115 }
116 #endif
117 #if 0
118 std::copy_n(mat.begin(), N*M, values.begin());
119 #else
120 for(Index c=0; c<mat.cols(); c++) for(Index r=0; r<mat.rows(); r++) (*this)(r,c)=mat(r,c);
121 #endif
122 }
123
126 {
127 values = mat.values;
128 return * this;
129 }
130
136 void checkBounds(std::size_t i, std::size_t j) const
137 {
138 if ( i <= 0 ) {
139 throw std::out_of_range("matrix error on rows : " + std::to_string(i) + " <= 0");
140 } else if ( j <= 0 ) {
141 throw std::out_of_range("matrix error on rows : " + std::to_string(j) + " <= 0");
142 } else if ( i > N ) {
143 throw std::out_of_range("matrix error on rows : " + std::to_string(i) + " < " + std::to_string(N));
144 } else if ( j > M ) {
145 throw std::out_of_range("matrix error on rows : " + std::to_string(j) + " < " + std::to_string(M));
146 }
147 }
148
150 std::size_t rows() const { return N; }
152 std::size_t cols() const { return M; }
153 const double *data() const { return values.data(); }
154 double *data() { return values.data(); }
155
156
157
162 double &operator[](std::size_t i)
163 {
164 return values[ i ];
165 }
166
170 double operator[](std::size_t i) const
171 {
172 return values[ i ];
173 }
174
181 double &operator()(std::size_t i, std::size_t j)
182 {
183 #ifndef NDEBUG
184 this->checkBounds(i + 1, j + 1);
185 #endif
186 return values [ j * N + i ];
187 }
188
193 double operator()(std::size_t i, std::size_t j) const
194 {
195 #ifndef NDEBUG
196 this->checkBounds(i + 1, j + 1);
197 #endif
198 return values [ j * N + i ];
199 }
200
206 template<std::size_t R, std::size_t C>
207 FloatMatrixF<R,C> operator()(std::size_t const (&r)[R], std::size_t const (&c)[C]) const
208 {
210 for ( std::size_t i = 0; i < R; ++i ) {
211 for ( std::size_t j = 0; j < C; ++j ) {
212 x(i, j) = (*this)(r[i], c[j]);
213 }
214 }
215 return x;
216 }
217#endif
224 double at(std::size_t i, std::size_t j) const
225 {
226 #ifndef NDEBUG
227 this->checkBounds(i, j);
228 #endif
229 return (*this)(i-1, j-1);
230 }
231
237 inline double &at(std::size_t i, std::size_t j)
238 {
239 #ifndef NDEBUG
240 this->checkBounds(i, j);
241 #endif
242 return (*this)(i-1, j-1);
243 }
244
245 static FloatMatrixF<N,M> fromColumns(FloatArrayF<N> const (&x)[M]) noexcept
246 {
248 for ( std::size_t r = 0; r < N; ++r) {
249 for ( std::size_t c = 0; c < M; ++c) {
250 ret(r,c) = x[c][r];
251 }
252 }
253 return ret;
254 }
255
256
258 template<std::size_t R, std::size_t C>
259 inline void assemble(const FloatMatrixF<R,C> &x, int const (&r)[R], int const (&c)[C] )
260 {
261 for ( std::size_t i = 0; i < R; ++i ) {
262 for ( std::size_t j = 0; j < C; ++j ) {
263 (*this)(r[i], c[j]) += x(i, j);
264 }
265 }
266 }
267
268
274 void setColumn(const FloatArrayF<N> &src, std::size_t c)
275 {
276 for ( std::size_t i = 0; i < N; i++ ) {
277 (*this)(i, c) = src[i];
278 }
279 }
280
286 void setRow(const FloatArrayF<M> &src, int r)
287 {
288 for ( std::size_t i = 0; i < M; i++ ) {
289 (*this)(r, i) = src[i];
290 }
291 }
292
298 FloatArrayF<N> column(std::size_t j) const
299 {
301 for ( std::size_t i = 0; i < N; i++ ) {
302 c[i] = (*this)(i, j);
303 }
304 return c;
305 }
306
310 template<std::size_t C, class = typename std::enable_if_t<C < M>>
311 FloatArrayF<N> column() const
312 {
313 FloatArrayF<N> c;
314 for ( std::size_t i = 0; i < N; i++ ) {
315 c[i] = (*this)(i, C);
316 }
317 return c;
318 }
319
323 template<std::size_t R, class = typename std::enable_if_t<R < N>>
324 FloatArrayF<M> row() const
325 {
326 FloatArrayF<M> r;
327 for ( std::size_t j = 0; j < M; j++ ) {
328 r[j] = (*this)(R, j);
329 }
330 return r;
331 }
332
341 template<std::size_t P>
342 void plusProductSymmUpper(const FloatMatrixF<P,N> &a, const FloatMatrixF<P,M> &b, double dV)
343 {
345 for ( std::size_t i = 0; i < N; ++i ) {
346 for ( std::size_t j = i; j < M; ++j ) {
347 double summ = 0.;
348 for ( std::size_t k = 0; k < P; ++k ) {
349 summ += a(k, i) * b(k, j);
350 }
351 (*this)(i, j) += summ * dV;
352 }
353 }
354 }
361 void plusDyadSymmUpper(const FloatArrayF<N> &a, double dV)
362 {
364 for ( std::size_t i = 0; i < N; ++i ) {
365 for ( std::size_t j = i; j < N; ++j ) {
366 (*this)(i, j) += a[i] * a[j] * dV;
367 }
368 }
369 }
376 template<std::size_t P>
377 void plusProductUnsym(const FloatMatrixF<P,N> &a, const FloatMatrixF<P,M> &b, double dV)
378 {
380 for ( std::size_t i = 0; i < N; ++i ) {
381 for ( std::size_t j = 0; j < M; ++j ) {
382 double summ = 0.;
383 for ( std::size_t k = 0; k < P; ++k ) {
384 summ += a(k, i) * b(k, j);
385 }
386 (*this)(i, j) += summ * dV;
387 }
388 }
389 }
396 void plusDyadUnsym(const FloatArray &a, const FloatArray &b, double dV)
397 {
399 for ( std::size_t i = 0; i < N; ++i ) {
400 for ( std::size_t j = 0; j < M; ++j ) {
401 (*this)(i, j) += a[i] * b[j] * dV;
402 }
403 }
404 }
408 void symmetrized()
409 {
410 for ( std::size_t i = 2; i <= this->rows(); i++ ) {
411 for ( std::size_t j = 1; j < i; j++ ) {
412 this->at(i, j) = this->at(j, i);
413 }
414 }
415 }
416
418 void printYourself(const std::string &name="FloatMatrixF") const
419 {
420 printf("%s (%zu x %zu): \n", name.c_str(), N, M);
421 if ( this->rows() <= 250 && this->cols() <= 250 ) {
422 for ( std::size_t i = 0; i < this->rows(); ++i ) {
423 for ( std::size_t j = 0; j < this->cols() && j < 100; ++j ) {
424 printf( "%10.3e ", (*this)(i, j) );
425 }
426 printf("\n");
427 }
428 } else {
429 for ( std::size_t i = 0; i < this->rows() && i < 20; ++i ) {
430 for ( std::size_t j = 0; j < this->cols() && j < 10; ++j ) {
431 printf( "%10.3e ", (*this)(i, j) );
432 }
433 if ( this->cols() > 10 ) printf(" ...");
434 printf("\n");
435 }
436 if ( this->cols() > 20 ) printf(" ...\n");
437 }
438 }
439
444 const double *givePointer() const { return data(); }
445 double *givePointer() { return data(); }
446
448 {
449 if ( !stream.write(data(), N*M) ) {
450 return CIO_IOERR;
451 }
452 return CIO_OK;
453 }
454
456 {
457 if ( !stream.read(data(), N*M) ) {
458 return CIO_IOERR;
459 }
460 return CIO_OK;
461 }
462
463 int givePackSize(DataStream &buff) const
464 {
465 return buff.givePackSizeOfDouble(N*M);
466 }
467};
468
469
471template<std::size_t N, std::size_t M, std::size_t R, std::size_t C>
472inline FloatMatrixF<N,M> assemble(const FloatMatrixF<R,C> &x, int const (&r)[R], int const (&c)[C] )
473{
475 for ( std::size_t i = 0; i < R; ++i ) {
476 for ( std::size_t j = 0; j < C; ++j ) {
477 out(r[i], c[j]) = x(i, j);
478 }
479 }
480 return out;
481}
482
483
484template<std::size_t N, std::size_t M>
485std::ostream & operator << ( std::ostream & out, const FloatMatrixF<N,M> & x )
486{
487 out << N << " " << M << " {";
488 for ( std::size_t i = 0; i < N; ++i ) {
489 for ( std::size_t j = 0; j < M; ++j ) {
490 out << " " << x(i, j);
491 }
492 out << ";";
493 }
494 out << "}";
495 return out;
496}
497
498template<std::size_t N, std::size_t M>
500{
502 _LOOP_FLOATMATRIX(x,r,c) out(r,c)=x(r,c)*a;
503 return out;
504}
505
506template<std::size_t N, std::size_t M>
508{
509 return a*x;
510}
511
512template<std::size_t N, std::size_t M>
514{
516 _LOOP_FLOATMATRIX(x,r,c) out(r,c)=x(r,c)/a;
517 return out;
518}
519
520template<std::size_t N, std::size_t M>
522{
524 _LOOP_FLOATMATRIX(x,r,c) out(r,c)=x(r,c)+y(r,c);
525 return out;
526}
527
528template<std::size_t N, std::size_t M>
530{
532 _LOOP_FLOATMATRIX(x,r,c) out(r,c)=x(r,c)-y(r,c);
533 return out;
534}
535
536template<std::size_t N, std::size_t M>
538{
539 _LOOP_FLOATMATRIX(x,r,c) x(r,c)+=y(r,c);
540 return x;
541}
542
543template<std::size_t N, std::size_t M>
545{
546 _LOOP_FLOATMATRIX(x,r,c) x(r,c)-=y(r,c);
547 return x;
548}
549
550template<std::size_t N, std::size_t M>
552{
553 _LOOP_FLOATMATRIX(x,r,c) x(r,c)*=a;
554 return x;
555}
556
558template<std::size_t N, std::size_t M>
560{
561 for ( auto &val : mat ) {
562 if ( !std::isfinite(val) ) {
563 return false;
564 }
565 }
566 return true;
567}
568
573template<std::size_t N, std::size_t NSD>
575{
577 for ( std::size_t i = 0; i < N; ++i ) {
578 for ( std::size_t j = 0; j < NSD; ++j ) {
579 out( j, i * NSD + j ) = n[j];
580 }
581 }
582 return out;
583}
584
590{
591 return {
592 normal[0], normal[1],
593 normal[1], -normal[0]
594 };
595}
596
598{
599 // Create a permutated vector of n, *always* length 1 and significantly different from n.
600 FloatArrayF<3> tangent = {normal[1], -normal[2], normal[0]};
601
602 // Construct orthogonal vector
603 double npn = dot(tangent, normal);
604 tangent += -npn * normal;
605 tangent /= norm(tangent);
606 auto bigent = cross(tangent, normal);
607
609 //out.setColumn(normal, 0);
610 //out.setColumn(bigent, 1);
611 //out.setColumn(tangent, 2);
612 out(0, 0) = normal[0];
613 out(0, 1) = normal[1];
614 out(0, 2) = normal[2];
615
616 out(1, 0) = bigent[0];
617 out(1, 1) = bigent[1];
618 out(1, 2) = bigent[2];
619
620 out(2, 0) = tangent[0];
621 out(2, 1) = tangent[1];
622 out(2, 2) = tangent[2];
623 return out;
624}
625
627template<std::size_t N, std::size_t M>
629{
631 for ( std::size_t i = 0; i < N; ++i ) {
632 for ( std::size_t j = 0; j < M; ++j ) {
633 out(j, i) = mat(i, j);
634 }
635 }
636 return out;
637}
638
640template<std::size_t N, std::size_t M, std::size_t P>
642{
645 for ( std::size_t i = 0; i < N; i++ ) {
646 for ( std::size_t j = 0; j < P; j++ ) {
647 double coeff = 0.;
648 for ( std::size_t k = 0; k < M; k++ ) {
649 coeff += a(i, k) * b(k, j);
650 }
651 out(i, j) = coeff;
652 }
653 }
654 return out;
655}
656
658template<std::size_t N, std::size_t M, std::size_t P>
660{
663 for ( std::size_t i = 0; i < N; i++ ) {
664 for ( std::size_t j = 0; j < P; j++ ) {
665 double coeff = 0.;
666 for ( std::size_t k = 0; k < M; k++ ) {
667 coeff += a(i, k) * b(j, k);
668 }
669 out(i, j) = coeff;
670 }
671 }
672 return out;
673}
674
676template<std::size_t N, std::size_t M, std::size_t P>
678{
681 for ( std::size_t i = 0; i < N; i++ ) {
682 for ( std::size_t j = 0; j < P; j++ ) {
683 double coeff = 0.;
684 for ( std::size_t k = 0; k < M; k++ ) {
685 coeff += a(k, i) * b(k, j);
686 }
687 out(i, j) = coeff;
688 }
689 }
690 return out;
691}
692
694template<std::size_t N, std::size_t M>
696{
697 FloatArrayF<N> out;
698 for ( std::size_t i = 0; i < N; i++ ) {
699 double sum = 0.;
700 for ( std::size_t j = 0; j < M; j++ ) {
701 sum += m(i, j) * x[j];
702 }
703 out[i] = sum;
704 }
705 return out;
706}
707
709template<std::size_t N, std::size_t M>
711{
712 FloatArrayF<N> out;
713 for ( std::size_t i = 0; i < N; i++ ) {
714 double sum = 0.;
715 for ( std::size_t j = 0; j < M; j++ ) {
716 sum += x[j] * m(j, i);
717 }
718 out[i] = sum;
719 }
720 return out;
721}
722
724template<std::size_t N, std::size_t M>
726{
727 return dot(x, m);
728}
729
731template<std::size_t N, std::size_t M>
733{
735 for ( std::size_t i = 0; i < N; ++i ) {
736 for ( std::size_t j = 0; j < M; ++j ) {
737 out(i, j) = a[i] * b[j];
738 }
739 }
740 return out;
741}
742
744template<std::size_t N, std::size_t M>
746{
747 return dot(Tdot(r, a), r);
748}
749
751template<std::size_t N, std::size_t M>
753{
754 return dotT(dot(r, a), r);
755}
756
760template<std::size_t N, std::size_t M>
761FloatArrayF<N> column(const FloatMatrixF<N,M> &mat, std::size_t col)
762{
763 FloatArrayF<N> ans;
764 for ( std::size_t row = 0; row < N; ++row ) {
765 ans[row] = mat(row, col);
766 }
767 return ans;
768}
769
775{
776 return {
777 v[0], v[8], v[7],
778 v[5], v[1], v[6],
779 v[4], v[3], v[2]
780 }; // note: column major order
781}
782
788{
789 return {
790 t(0, 0),
791 t(1, 1),
792 t(2, 2),
793 t(1, 2),
794 t(0, 2),
795 t(0, 1),
796 t(2, 1),
797 t(2, 0),
798 t(1, 0)
799 };
800}
801
807{
808 return {
809 v[0], v[5], v[4],
810 v[5], v[1], v[3],
811 v[4], v[3], v[2]
812 }; // note: column-major order
813}
814
820{
821 return {
822 t(0, 0),
823 t(1, 1),
824 t(2, 2),
825 0.5 * ( t(1, 2) + t(2, 1) ),
826 0.5 * ( t(0, 2) + t(2, 0) ),
827 0.5 * ( t(0, 1) + t(1, 0) )
828 };
829}
830
836{
837 return {
838 v[0], 0.5*v[5], 0.5*v[4],
839 0.5*v[5], v[1], 0.5*v[3],
840 0.5*v[4], 0.5*v[3], v[2]
841 }; // note: column-major order
842}
843
849{
850 return {
851 t(0, 0),
852 t(1, 1),
853 t(2, 2),
854 ( t(1, 2) + t(2, 1) ),
855 ( t(0, 2) + t(2, 0) ),
856 ( t(0, 1) + t(1, 0) )
857 };
858}
859
863template<std::size_t N>
865{
867 for ( std::size_t i = 0; i < N; ++i ) {
868 out(i, i) = v[i];
869 }
870 return out;
871}
872
873
877template<std::size_t N>
879{
880 FloatArrayF<N> out;
881 for ( std::size_t i = 0; i < N; ++i ) {
882 out[i] = m(i, i);
883 }
884 return out;
885}
886
890template<std::size_t N, std::size_t M>
892{
894 for(std::size_t c=0; c<m.cols(); c++) for(std::size_t r=0; r<m.rows(); r++) out[c*m.rows()+r]=m(r,c);
895 return out;
896}
897
902#if 0
903void swap_46(FloatMatrixF<6,6> &t)
904{
905 std::swap( t(3, 0), t(5, 0) );
906 std::swap( t(3, 1), t(5, 1) );
907 std::swap( t(3, 2), t(5, 2) );
908 std::swap( t(0, 3), t(0, 5) );
909 std::swap( t(1, 3), t(1, 5) );
910 std::swap( t(2, 3), t(2, 5) );
911 std::swap( t(3, 3), t(5, 5) );
912 std::swap( t(4, 3), t(4, 5) );
913 std::swap( t(5, 3), t(3, 5) );
914 std::swap( t(3, 4), t(5, 4) );
915}
916
918{
919 // OOFEM: 11, 22, 33, 23, 13, 12, 32, 31, 21
920 // UMAT: 11, 22, 33, 12, 13, 23, 32, 21, 31
921
922 std::array<std::size_t, 9> abq2oo = {0, 1, 2, 5, 4, 3, 6, 8, 7};
923
925 for ( std::size_t i = 0; i < 9; i++ ) {
926 for ( std::size_t j = 0; j < 9; j++ ) {
927 tmp(i, j) = t(abq2oo[ i ], abq2oo[ j ]);
928 }
929 }
930
931 t = tmp;
932}
933#endif
934
936template<std::size_t N,std::size_t M>
938{
939 return FloatMatrixF<N,M>();
940}
941
943template<std::size_t N>
945{
947 for ( std::size_t i = 0; i < N; ++i ) {
948 out(i, i) = 1.;
949 }
950 return out;
951}
952
955 2./3., -1./3., -1/3., 0., 0., 0.,
956 -1./3., 2./3., -1/3., 0., 0., 0.,
957 -1./3., -1./3., 2/3., 0., 0., 0.,
958 0., 0., 0., 0.5, 0., 0.,
959 0., 0., 0., 0., 0.5, 0.,
960 0., 0., 0., 0., 0., 0.5,
961};
962
965 1., 1., 1., 0., 0., 0.,
966 1., 1., 1., 0., 0., 0.,
967 1., 1., 1., 0., 0., 0.,
968 0., 0., 0., 0., 0., 0.,
969 0., 0., 0., 0., 0., 0.,
970 0., 0., 0., 0., 0., 0.,
971};
972
973
980template<std::size_t N, std::size_t NSD>
982{
984 for ( std::size_t i = 0; i < N; ++i ) {
985 for ( std::size_t j = 0; j < NSD; ++j ) {
986 out( j, i * NSD + j ) = n[j];
987 }
988 }
989 return out;
990}
991
993template<std::size_t N>
995{
997 for ( std::size_t j = 0, k = 0; j < dN.rows(); j++, k += 3 ) {
998 B(0, k + 0) = B(3, k + 1) = B(4, k + 2) = dN(0, j);
999 B(1, k + 1) = B(3, k + 0) = B(5, k + 2) = dN(1, j);
1000 B(2, k + 2) = B(4, k + 0) = B(5, k + 1) = dN(2, j);
1001 }
1002 return B;
1003}
1004
1006template<std::size_t N>
1008{
1010 for ( std::size_t j = 0, k = 0; j < N; j++, k += 2 ) {
1011 B(0, k + 0) = B(2, k + 1) = dN(0, j);
1012 B(1, k + 1) = B(2, k + 0) = dN(1, j);
1013 }
1014 return B;
1015}
1016
1019
1023template<std::size_t N>
1024double trace(const FloatMatrixF<N,N> &mat)
1025{
1026 double s = 0.;
1027 for ( std::size_t i = 0; i < N; ++i ) {
1028 s += mat(i, i);
1029 }
1030 return s;
1031}
1032
1038template<std::size_t N>
1040{
1041 double n = 0.;
1042 _LOOP_FLOATMATRIX(mat,r,c) n+=mat(r,c)*mat(r,c);
1043 return std::sqrt( n );
1044 //return std::sqrt( std::inner_product(mat.values.begin(), mat.values.end(), mat.values.begin(), 0.) );
1045}
1046
1052template<std::size_t N>
1053double norm(const FloatMatrixF<N,N> &mat, int p=1)
1054{
1055 if ( p == 1 ) {
1056 double max_col = 0.;
1057 for ( std::size_t j = 0; j < N; j++ ) {
1058 double col_sum = 0.;
1059 for ( std::size_t i = 0; i < N; i++ ) {
1060 col_sum += fabs( mat(i, j) );
1061 }
1062 if ( col_sum > max_col ) {
1063 max_col = col_sum;
1064 }
1065 }
1066 return max_col;
1067 } else if ( p == 2 ) {
1068 auto e = eig(transpose(mat) * mat, 1);
1069 return sqrt(e.first(0));
1070 }
1071}
1072
1080template<std::size_t N>
1081double rcond(const FloatMatrixF<N,N> &mat, int p=1)
1082{
1084 double anorm = norm(mat, p);
1085 if ( det(mat) <= 1e-6 * anorm ) {
1086 return 0.;
1087 }
1088 return 1. / ( norm(inv(mat)) * anorm, p );
1089}
1090
1092inline double det(const FloatMatrixF<2,2> &mat)
1093{
1094 return mat(0, 0) * mat(1, 1) - mat(0, 1) * mat(1, 0);
1095}
1096
1098inline double det(const FloatMatrixF<3,3> &mat)
1099{
1100 return mat(0, 0) * mat(1, 1) * mat(2, 2) + mat(0, 1) * mat(1, 2) * mat(2, 0) +
1101 mat(0, 2) * mat(1, 0) * mat(2, 1) - mat(0, 2) * mat(1, 1) * mat(2, 0) -
1102 mat(1, 2) * mat(2, 1) * mat(0, 0) - mat(2, 2) * mat(0, 1) * mat(1, 0);
1103}
1104
1105
1107inline FloatMatrixF<2,2> inv_22(const FloatMatrixF<2,2> &mat, double /*zeropiv*/)
1108{
1110 double d = det(mat);
1111 out(0, 0) = mat(1, 1) / d;
1112 out(1, 0) = -mat(1, 0) / d;
1113 out(0, 1) = -mat(0, 1) / d;
1114 out(1, 1) = mat(0, 0) / d;
1115 return out;
1116}
1117
1119inline FloatMatrixF<3,3> inv_33(const FloatMatrixF<3,3> &mat, double /*zeropiv*/)
1120{
1122 double d = det(mat);
1123 out(0, 0) = ( mat(1, 1) * mat(2, 2) - mat(1, 2) * mat(2, 1) ) / d;
1124 out(1, 0) = ( mat(1, 2) * mat(2, 0) - mat(1, 0) * mat(2, 2) ) / d;
1125 out(2, 0) = ( mat(1, 0) * mat(2, 1) - mat(1, 1) * mat(2, 0) ) / d;
1126 out(0, 1) = ( mat(0, 2) * mat(2, 1) - mat(0, 1) * mat(2, 2) ) / d;
1127 out(1, 1) = ( mat(0, 0) * mat(2, 2) - mat(0, 2) * mat(2, 0) ) / d;
1128 out(2, 1) = ( mat(0, 1) * mat(2, 0) - mat(0, 0) * mat(2, 1) ) / d;
1129 out(0, 2) = ( mat(0, 1) * mat(1, 2) - mat(0, 2) * mat(1, 1) ) / d;
1130 out(1, 2) = ( mat(0, 2) * mat(1, 0) - mat(0, 0) * mat(1, 2) ) / d;
1131 out(2, 2) = ( mat(0, 0) * mat(1, 1) - mat(0, 1) * mat(1, 0) ) / d;
1132 return out;
1133}
1134
1135
1137template<std::size_t N>
1138FloatMatrixF<N,N> inv(const FloatMatrixF<N,N> &mat, double zeropiv=1e-24)
1139{
1140 if constexpr (N==2) return inv_22(mat,zeropiv);
1141 if constexpr (N==3) return inv_33(mat,zeropiv);
1142 // gaussian elimination - slow but safe
1143 auto tmp = mat;
1144 // initialize answer to be unity matrix;
1145 auto out = eye<N>();
1146 // lower triangle elimination by columns
1147 for ( std::size_t i = 1; i < N; i++ ) {
1148 double piv = tmp.at(i, i);
1149 if ( std::abs(piv) <= zeropiv ) {
1150 OOFEM_ERROR("pivot (%d,%d) to close to small", (int)i, (int)i);
1151 }
1152 for ( std::size_t j = i + 1; j <= N; j++ ) {
1153 double linkomb = tmp.at(j, i) / tmp.at(i, i);
1154 for ( std::size_t k = i; k <= N; k++ ) {
1155 tmp.at(j, k) -= tmp.at(i, k) * linkomb;
1156 }
1157 for ( std::size_t k = 1; k <= N; k++ ) {
1158 out.at(j, k) -= out.at(i, k) * linkomb;
1159 }
1160 }
1161 }
1162 // upper triangle elimination by columns
1163 for ( std::size_t i = N; i > 1; i-- ) {
1164 double piv = tmp.at(i, i);
1165 for ( std::size_t j = i - 1; j > 0; j-- ) {
1166 double linkomb = tmp.at(j, i) / piv;
1167 for ( std::size_t k = i; k > 0; k-- ) {
1168 tmp.at(j, k) -= tmp.at(i, k) * linkomb;
1169 }
1170 for ( std::size_t k = N; k > 0; k-- ) {
1171 out.at(j, k) -= out.at(i, k) * linkomb;
1172 }
1173 }
1174 }
1175 // diagonal scaling
1176 for ( std::size_t i = 1; i <= N; i++ ) {
1177 for ( std::size_t j = 1; j <= N; j++ ) {
1178 out.at(i, j) /= tmp.at(i, i);
1179 }
1180 }
1181 return out;
1182}
1183
1184
1191template<std::size_t N>
1192std::pair<FloatArrayF<N>, FloatMatrixF<N,N>> eig(const FloatMatrixF<N,N> &mat, int nf=9)
1193{
1194 FloatArrayF<N> eval = diag(mat);
1196
1197 double sum = 0.0;
1198 for ( std::size_t i = 0; i < N; ++i ) {
1199 for ( std::size_t j = 0; j < N; ++j ) {
1200 sum += fabs( mat(i, j) );
1201 }
1202 }
1203
1204 if ( sum <= 0.0 ) {
1205 return {zeros<N>(), eye<N>()};
1206 }
1207
1208 auto m = mat;
1209 /* ---- REDUCE MATRIX TO DIAGONAL ---------------- */
1210 double c_b2 = .10;
1211 double tol = pow(c_b2, nf);
1212 int ite = 0;
1213 double ssum;
1214 do {
1215 ssum = 0.0;
1216 for ( std::size_t j = 1; j < N; ++j ) {
1217 for ( std::size_t i = 0; i < j; ++i ) {
1218 if ( ( fabs( m(i, j) ) / sum ) > tol ) {
1219 ssum += fabs( m(i, j) );
1220 /* ---- CALCULATE ROTATION ANGLE ----------------- */
1221 double aa = atan2( m(i, j) * 2.0, eval[i] - eval[j] ) / 2.0;
1222 double si = sin(aa);
1223 double co = cos(aa);
1224 /*
1225 * // ---- MODIFY "I" AND "J" COLUMNS OF "A" AND "V"
1226 * for (k = 0; k < neq; ++k) {
1227 * tt = m(k, i);
1228 * m(k, i) = co * tt + si * m(k, j);
1229 * m(k, j) = -si * tt + co * m(k, j);
1230 * tt = v(k, i);
1231 * v(k, i) = co * tt + si * v(k, j);
1232 * // L500:
1233 * v(k, j) = -si * tt + co * v(k, j);
1234 * }
1235 * // ---- MODIFY DIAGONAL TERMS --------------------
1236 * m(i, i) = co * m(i, i) + si * m(j, i);
1237 * m(j, j) = -si * m(i, j) + co * m(j, j);
1238 * m(i, j) = 0.0;
1239 * // ---- MAKE "A" MATRIX SYMMETRICAL --------------
1240 * for (k = 1; k <= neq; ++k) {
1241 * m(i, k) = m(k, i);
1242 * m(j, k) = m(k, j);
1243 * // L600:
1244 * }
1245 */
1246 // ---- MODIFY "I" AND "J" COLUMNS OF "A" AND "V"
1247 for ( std::size_t k = 0; k < i; ++k ) {
1248 double tt2 = m(k, i);
1249 m(k, i) = co * tt2 + si * m(k, j);
1250 m(k, j) = -si * tt2 + co * m(k, j);
1251 tt2 = v(k, i);
1252 v(k, i) = co * tt2 + si * v(k, j);
1253 v(k, j) = -si * tt2 + co * v(k, j);
1254 }
1255
1256 // diagonal term (i,i)
1257 double tt = eval[i];
1258 eval[i] = co * tt + si * m(i, j);
1259 double aij = -si * tt + co * m(i, j);
1260 tt = v(i, i);
1261 v(i, i) = co * tt + si * v(i, j);
1262 v(i, j) = -si * tt + co * v(i, j);
1263
1264 for ( std::size_t k = i + 1; k < j; ++k ) {
1265 double tt2 = m(i, k);
1266 m(i, k) = co * tt2 + si * m(k, j);
1267 m(k, j) = -si * tt2 + co * m(k, j);
1268 tt2 = v(k, i);
1269 v(k, i) = co * tt2 + si * v(k, j);
1270 v(k, j) = -si * tt2 + co * v(k, j);
1271 }
1272
1273 // diagonal term (j,j)
1274 tt = m(i, j);
1275 double aji = co * tt + si * eval[j];
1276 eval[j] = -si * tt + co * eval[j];
1277
1278 tt = v(j, i);
1279 v(j, i) = co * tt + si * v(j, j);
1280 v(j, j) = -si * tt + co * v(j, j);
1281 //
1282 for ( std::size_t k = j + 1; k < N; ++k ) {
1283 double tt2 = m(i, k);
1284 m(i, k) = co * tt2 + si * m(j, k);
1285 m(j, k) = -si * tt2 + co * m(j, k);
1286 tt2 = v(k, i);
1287 v(k, i) = co * tt2 + si * v(k, j);
1288 v(k, j) = -si * tt2 + co * v(k, j);
1289 }
1290
1291 // ---- MODIFY DIAGONAL TERMS --------------------
1292 eval[i] = co * eval[i] + si * aji;
1293 eval[j] = -si * aij + co * eval[j];
1294 m(i, j) = 0.0;
1295 } else {
1296 /* ---- A(I,J) MADE ZERO BY ROTATION ------------- */
1297 }
1298 }
1299 }
1300 /* ---- CHECK FOR CONVERGENCE -------------------- */
1301 if ( ++ite > 50 ) {
1302 throw std::runtime_error("eig computation failed");
1303 }
1304 } while ( fabs(ssum) / sum > tol );
1305 return {eval, v};
1306}
1307
1308
1314template<std::size_t N>
1315std::pair<FloatArrayF<N>, FloatMatrixF<N,N>> eig_inverse(const FloatMatrixF<N,N> &mat)
1316{
1317 int nitem = 100;
1318 double rtol = 1e-12;
1319
1321 std::array<FloatArrayF<N>, N> x;
1322 for ( std::size_t i = 0; i < N; ++i ) {
1323 w[i] += 1.;
1324 x[i][i] = 1.;
1325 }
1326 auto invmat = inv(mat);
1327
1328 for ( int it = 0; it < nitem; it++ ) {
1329 auto z = x;
1330 // solve matrix equation K.X = M.X
1331 for ( std::size_t i = 0; i < N; ++i ) {
1332 x[i] = dot(invmat, z[i]);
1333 }
1334
1335 // evaluation of Rayleigh quotients
1336 auto old_w = w;
1337 for ( std::size_t i = 0; i < N; i++ ) {
1338 w[i] = dot(z[i], x[i]) / dot(x[i], x[i]);
1339 }
1340
1341 orthogonalize(x);
1342
1343 // check convergence
1344 if ( norm2(old_w - w) <= norm2(w) * rtol ) {
1345 break;
1346 }
1347 }
1348
1349 return {w, x};
1350}
1351
1352
1353template<std::size_t N>
1354void orthogonalize(std::array<FloatArrayF<N>, N> &x)
1355{
1356 for ( std::size_t j = 0; j < N; j++ ) {
1357 auto t = x[j];
1358 for ( std::size_t ii = 0; ii < j; ii++ ) {
1359 x[j] -= dot(x[ii], t) * x[ii];
1360 }
1361 x[j] *= 1.0 / norm(x[j]);
1362 }
1363}
1364
1365
1366#if 0
1367template<>
1368inline std::pair<FloatArrayF<2>, FloatMatrixF<2,2>> eig(const FloatMatrixF<2,2> &mat, int nf)
1369{
1370 double b = - (mat(0,0) + mat(1,1))/2.;
1371 double c = mat(0,0) * mat(1,1) - mat(0,1) * mat(1,0);
1372 FloatArrayF<2> vals = {
1373 -b + std::sqrt(b*b - c),
1374 -b - std::sqrt(b*b - c)
1375 };
1376 FloatMatrixF<2,2> vecs;
1377 OOFEM_ERROR("TODO"); // is this even worth specializing? I don't think we ever use it for 2x2. Typically just 3x3, 6x6, 9x9
1378 return {vals, vecs};
1379}
1380#endif
1381
1388template<std::size_t N>
1389std::pair<bool, FloatArrayF<N>> solve_check(FloatMatrixF<N,N> mtrx, const FloatArrayF<N> &b, double zeropiv = 1e-20)
1390{
1391 auto answer = b;
1392 // initialize answer to be unity matrix;
1393 // lower triangle elimination by columns
1394 for ( std::size_t i = 0; i < N - 1; i++ ) {
1395 // find the suitable row and pivot
1396 double piv = fabs( mtrx(i, i) );
1397 std::size_t pivRow = i;
1398 for ( std::size_t j = i + 1; j < N; j++ ) {
1399 if ( fabs( mtrx(j, i) ) > piv ) {
1400 pivRow = j;
1401 piv = fabs( mtrx(j, i) );
1402 }
1403 }
1404
1405 if ( piv <= zeropiv ) {
1406 return {false, zeros<N>()};
1407 }
1408
1409 // exchange rows
1410 if ( pivRow != i ) {
1411 for ( std::size_t j = i; j < N; j++ ) {
1412 double help = mtrx(i, j);
1413 mtrx(i, j) = mtrx(pivRow, j);
1414 mtrx(pivRow, j) = help;
1415 }
1416 double help = answer[i];
1417 answer[i] = answer[pivRow];
1418 answer[pivRow] = help;
1419 }
1420
1421 for ( std::size_t j = i + 1; j < N; j++ ) {
1422 double linkomb = mtrx(j, i) / mtrx(i, i);
1423 for ( std::size_t k = i; k < N; k++ ) {
1424 mtrx(j, k) -= mtrx(i, k) * linkomb;
1425 }
1426
1427 answer[j] -= answer[i] * linkomb;
1428 }
1429 }
1430
1431 // back substitution
1432 for ( int i = N - 1; i >= 0; i-- ) {
1433 double help = 0.;
1434 for ( std::size_t j = i + 1; j < N; j++ ) {
1435 help += mtrx(i, j) * answer[j];
1436 }
1437
1438 answer[i] = ( answer[i] - help ) / mtrx(i, i);
1439 }
1440 return {true, answer};
1441}
1442
1443
1450template<std::size_t N>
1451FloatArrayF<N> solve(FloatMatrixF<N,N> mtrx, const FloatArrayF<N> &b, double zeropiv=1e-20)
1452{
1453 auto tmp = solve_check(mtrx, b, zeropiv);
1454 if ( tmp.first ) {
1455 return tmp.second;
1456 } else {
1457 throw std::runtime_error("Singular pivot encountered");
1458 }
1459}
1460
1467template<std::size_t N, std::size_t M>
1468FloatMatrixF<N,M> solve(FloatMatrixF<N,N> mtrx, const FloatMatrixF<N,M> &B, double zeropiv=1e-20)
1469{
1470 auto answer = B;
1471 // initialize answer to be unity matrix;
1472 // lower triangle elimination by columns
1473 for ( std::size_t i = 0; i < N - 1; i++ ) {
1474 // find the suitable row and pivot
1475 double piv = fabs( mtrx(i, i) );
1476 std::size_t pivRow = i;
1477 for ( std::size_t j = i + 1; j < N; j++ ) {
1478 if ( fabs( mtrx(j, i) ) > piv ) {
1479 pivRow = j;
1480 piv = fabs( mtrx(j, i) );
1481 }
1482 }
1483
1484 if ( fabs(piv) < zeropiv ) {
1485 throw std::runtime_error("pivot too small, matrix problem could not be solved");
1486 }
1487
1488 // exchange rows
1489 if ( pivRow != i ) {
1490 for ( std::size_t j = i; j < N; j++ ) {
1491 double help = mtrx(i, j);
1492 mtrx(i, j) = mtrx(pivRow, j);
1493 mtrx(pivRow, j) = help;
1494 }
1495
1496 for ( std::size_t j = 0; j < M; j++ ) {
1497 double help = answer(i, j);
1498 answer(i, j) = answer(pivRow, j);
1499 answer(pivRow, j) = help;
1500 }
1501 }
1502
1503 for ( std::size_t j = i + 1; j < N; j++ ) {
1504 double linkomb = mtrx(j, i) / mtrx(i, i);
1505 for ( std::size_t k = i; k < N; k++ ) {
1506 mtrx(j, k) -= mtrx(i, k) * linkomb;
1507 }
1508
1509 for ( std::size_t k = 0; k < M; k++ ) {
1510 answer(j, k) -= answer(i, k) * linkomb;
1511 }
1512 }
1513 }
1514
1515 // back substitution
1516 for ( std::size_t i = N - 1; i >= 0; i-- ) {
1517 for ( std::size_t k = 0; k < M; k++ ) {
1518 double help = 0.;
1519 for ( std::size_t j = i + 1; j < N; j++ ) {
1520 help += mtrx(i, j) * answer(j, k);
1521 }
1522
1523 answer(i, k) = ( answer(i, k) - help ) / mtrx(i, i);
1524 }
1525 }
1526 return answer;
1527}
1528
1529
1530} // end namespace oofem
1531#endif // floatmatrixf_h
#define N(a, b)
virtual int read(int *data, std::size_t count)=0
Reads count integer values into array pointed by data.
virtual int givePackSizeOfDouble(std::size_t count)=0
virtual int write(const int *data, std::size_t count)=0
Writes count integer values from array pointed by data.
contextIOResultType restoreYourself(DataStream &stream)
double operator[](std::size_t i) const
void checkBounds(std::size_t i, std::size_t j) const
void setRow(const FloatArrayF< M > &src, int r)
double & at(std::size_t i, std::size_t j)
contextIOResultType storeYourself(DataStream &stream) const
void setColumn(const FloatArrayF< N > &src, std::size_t c)
double & operator()(std::size_t i, std::size_t j)
FloatMatrixF(const FloatMatrix &mat)
FloatMatrix conversion constructor.
FloatMatrixF(const FloatMatrixF< N, M > &mat) noexcept
Copy constructor.
FloatMatrixF< R, C > operator()(std::size_t const (&r)[R], std::size_t const (&c)[C]) const
FloatMatrixF() noexcept
std::array< double, N *M > values
Values of matrix stored column wise.
const double * givePointer() const
const double * data() const
FloatArrayF< N > column(std::size_t j) const
double operator()(std::size_t i, std::size_t j) const
double at(std::size_t i, std::size_t j) const
std::size_t cols() const
Returns number of columns of receiver.
FloatMatrixF & operator=(const FloatMatrixF< N, M > &mat)
Assignment operator.
void printYourself(const std::string &name="FloatMatrixF") const
Prints matrix to stdout. Useful for debugging.
double & operator[](std::size_t i)
std::size_t rows() const
Returns number of rows of receiver.
void assemble(const FloatMatrixF< R, C > &x, int const (&r)[R], int const (&c)[C])
Assemble x into self.
static FloatMatrixF< N, M > fromColumns(FloatArrayF< N > const (&x)[M]) noexcept
int givePackSize(DataStream &buff) const
FloatMatrixF(V... x) noexcept
#define OOFEM_ERROR(...)
Definition error.h:79
#define _LOOP_FLOATMATRIX(M, r, c)
FloatArrayF< 6 > to_voigt_stress_33(const FloatMatrixF< 3, 3 > &t)
FloatArray operator+(const FloatArray &x, const FloatArray &y)
Definition floatarray.C:978
double norm(const FloatArray &x)
OOFEM_EXPORT FloatArray operator/(const FloatArray &x, const double &a)
FloatArrayF< 6 > to_voigt_strain_33(const FloatMatrixF< 3, 3 > &t)
FloatMatrixF< N *3, NSD > Nmatrix(const FloatArrayF< N > &n)
FloatMatrixF< M, N > transpose(const FloatMatrixF< N, M > &mat)
Constructs transposed matrix.
FloatArray operator-(const FloatArray &x, const FloatArray &y)
Definition floatarray.C:985
FloatMatrixF< N, P > Tdot(const FloatMatrixF< M, N > &a, const FloatMatrixF< M, P > &b)
Computes .
std::pair< bool, FloatArrayF< N > > solve_check(FloatMatrixF< N, N > mtrx, const FloatArrayF< N > &b, double zeropiv=1e-20)
FloatMatrixF< 3, 3 > from_voigt_form_9(const FloatArrayF< 9 > &v)
FloatMatrixF< N, M > dyad(const FloatArrayF< N > &a, const FloatArrayF< M > &b)
Computes the dyadic product .
FloatMatrixF< 3, 3 > from_voigt_strain_6(const FloatArrayF< 6 > &v)
FloatArrayF< N > assemble(const FloatArrayF< M > &x, int const (&c)[M])
Assemble components into zero matrix.
std::pair< FloatArrayF< N >, FloatMatrixF< N, N > > eig(const FloatMatrixF< N, N > &mat, int nf=9)
FloatMatrixF< N, P > dotT(const FloatMatrixF< N, M > &a, const FloatMatrixF< P, M > &b)
Computes .
FloatMatrixF< 3, 3 > from_voigt_stress_6(const FloatArrayF< 6 > &v)
FloatMatrixF< 6, N *3 > Bmatrix_3d(const FloatMatrixF< 3, N > &dN)
Constructs the B matrix for 3D momentum balance problems.
const FloatMatrixF< 6, 6 > I6_I6
I(x)I expressed in Voigt form.
FloatArray & operator+=(FloatArray &x, const FloatArray &y)
Definition floatarray.C:992
std::ostream & operator<<(std ::ostream &out, const Dictionary &r)
Definition dictionary.C:247
double det(const FloatMatrixF< 2, 2 > &mat)
Computes the determinant.
double frobeniusNorm(const FloatMatrixF< N, N > &mat)
FloatArrayF< 9 > to_voigt_form_33(const FloatMatrixF< 3, 3 > &t)
void orthogonalize(std::array< FloatArrayF< N >, N > &x)
int Index
Definition numerics.h:73
FloatArrayF< 3 > cross(const FloatArrayF< 3 > &x, const FloatArrayF< 3 > &y)
Computes $ x \cross y $.
double sum(const FloatArray &x)
double rcond(const FloatMatrixF< N, N > &mat, int p=1)
FloatArrayF< N > solve(FloatMatrixF< N, N > mtrx, const FloatArrayF< N > &b, double zeropiv=1e-20)
FloatMatrixF< M, M > rotate(FloatMatrixF< N, N > &a, const FloatMatrixF< N, M > &r)
Computes .
FloatMatrixF< 3, N *2 > Bmatrix_2d(const FloatMatrixF< 2, N > &dN)
Constructs the B matrix for plane stress momentum balance problems.
const FloatMatrixF< 6, 6 > I_dev6
I_dev matrix in Voigt (stress) form.
FloatMatrixF< N, N > diag(const FloatArrayF< N > &v)
double dot(const FloatArray &x, const FloatArray &y)
bool isfinite(const FloatArray &x)
std::pair< FloatArrayF< N >, FloatMatrixF< N, N > > eig_inverse(const FloatMatrixF< N, N > &mat)
FloatMatrixF< N, M > zero()
Constructs a zero matrix (this is the default behavior when constructing a matrix,...
FloatArray & operator-=(FloatArray &x, const FloatArray &y)
Definition floatarray.C:998
FloatMatrixF< N, N > inv(const FloatMatrixF< N, N > &mat, double zeropiv=1e-24)
Computes the inverse.
FloatMatrixF< 2, 2 > local_cs(const FloatArrayF< 2 > &normal)
FloatMatrixF< M, M > unrotate(FloatMatrixF< N, N > &a, const FloatMatrixF< M, N > &r)
Computes .
FloatMatrixF< 2, 2 > inv_22(const FloatMatrixF< 2, 2 > &mat, double)
Computes the inverse.
FloatArray operator*(const double &a, const FloatArray &x)
Definition floatarray.C:964
FloatMatrixF< 3, 3 > inv_33(const FloatMatrixF< 3, 3 > &mat, double)
Computes the inverse.
void swap_46(FloatArrayF< 6 > &t)
FloatArrayF< N > zeros()
For more readable code.
FloatArray & operator*=(FloatArray &x, const double &a)
Vector multiplication by scalar.
Definition floatarray.C:958
@ CIO_IOERR
General IO error.
double trace(const FloatMatrixF< N, N > &mat)
FloatMatrixF< N, N > eye()
Constructs an identity matrix.
FloatArrayF< N > column(const FloatMatrixF< N, M > &mat, std::size_t col)
FloatArrayF< N *M > flatten(const FloatMatrixF< N, M > &m)
#define OOFEM_EXPORT
Definition oofemcfg.h:7

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011