OOFEM 3.0
Loading...
Searching...
No Matches
tensor2.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#include "floatmatrix.h"
36#include "floatarray.h"
37#include "mathfem.h"
38#include "index.h"
39#include "tensor1.h"
40#include "tensor4.h"
41#pragma once
42
43using namespace FTensor;
44
45
46
55
56namespace oofem {
57class Tensor2_3d : public Tensor2< double, 3, 3 >
58{
59public:
60 using Tensor2< double, 3, 3 >::Tensor2;
61
66
68 this->data [ 0 ] [ 0 ] = 0;
69 this->data [ 0 ] [ 1 ] = 0.;
70 this->data [ 0 ] [ 2 ] = 0.;
71 this->data [ 1 ] [ 0 ] = 0.;
72 this->data [ 1 ] [ 1 ] = 0.;
73 this->data [ 1 ] [ 2 ] = 0.;
74 this->data [ 2 ] [ 0 ] = 0.;
75 this->data [ 2 ] [ 1 ] = 0.;
76 this->data [ 2 ] [ 2 ] = 0.;
77 }
78
82
84 this->data [ 0 ] [ 0 ] = array.at(1);
85 this->data [ 0 ] [ 1 ] = array.at(6);
86 this->data [ 0 ] [ 2 ] = array.at(5);
87 this->data [ 1 ] [ 0 ] = array.at(9);
88 this->data [ 1 ] [ 1 ] = array.at(2);
89 this->data [ 1 ] [ 2 ] = array.at(4);
90 this->data [ 2 ] [ 0 ] = array.at(8);
91 this->data [ 2 ] [ 1 ] = array.at(7);
92 this->data [ 2 ] [ 2 ] = array.at(3);
93 }
94
98
100 {
101 return {
102 this->operator()(0, 0),
103 this->operator()(1, 1),
104 this->operator()(2, 2),
105 this->operator()(1, 2),
106 this->operator()(0, 2),
107 this->operator()(0, 1),
108 this->operator()(2, 1),
109 this->operator()(2, 0),
110 this->operator()(1, 0)
111 };
112 }
113
114
121 Tensor2_3d computeTensorPower(double pow, int nf = 10)
122 {
123 auto [ eVals, eVecs ] = this->eigs(nf);
124 return computeTensorPowerFromEigs(eVals, eVecs, pow);
125 }
126
134
135 static Tensor2_3d computeTensorPowerFromEigs(const FloatArray &eVals, const FloatMatrix &eVecs, double m)
136 {
137 Tensor2_3d Cpow;
138 for ( int i = 0; i < 3; i++ ) {
139 for ( int j = 0; j < 3; j++ ) {
140 Cpow(i, j) = pow(eVals.at(1), m) * eVecs(i, 0) * eVecs(j, 0) + pow(eVals.at(2), m) * eVecs(i, 1) * eVecs(j, 1) + pow(eVals.at(3), m) * eVecs(i, 2) * eVecs(j, 2);
141 }
142 }
143 return Cpow;
144 }
145
154 static Tensor2_3d computeTensorPowerFromEigs(const FloatArray &eVals, const FloatMatrix &eVecs, double m, const FloatArray &coeff)
155 {
156 Tensor2_3d Cpow;
157 for ( int i = 0; i < 3; i++ ) {
158 for ( int j = 0; j < 3; j++ ) {
159 Cpow(i, j) -= coeff.at(1) * pow(eVals.at(1), m) * eVecs.at(i, 0) * eVecs.at(j, 0) + coeff.at(2) * pow(eVals.at(2), m) * eVecs.at(i, 1) * eVecs.at(j, 1) + coeff.at(3) * pow(eVals.at(3), m) * eVecs.at(i, 2) * eVecs.at(j, 2);
160 }
161 }
162 return Cpow;
163 }
164
165
166
174 std::pair< FloatArrayF< 3 >, FloatMatrixF< 3, 3 > >eigs(int nf = 15) const
175 {
176 Tensor2_3d copy(* this);
177 // Local variables
178 int neq = 3;
179 double c_b2 = .10;
180
183
184 for ( int i = 1; i <= neq; i++ ) {
185 eval.at(i) = copy(i - 1, i - 1);
186 }
187
188 double tol = pow(c_b2, nf);
189 double sum = 0.0;
190 for ( int i = 1; i <= neq; ++i ) {
191 for ( int j = 1; j <= neq; ++j ) {
192 sum += fabs(copy(i - 1, j - 1) );
193 v.at(i, j) = 0.0;
194 }
195
196 v.at(i, i) = 1.0;
197 }
198
199 if ( sum > 0.0 ) {
200 // ---- REDUCE MATRIX TO DIAGONAL ----------------
201 int ite = 0;
202 double ssum;
203 do {
204 ssum = 0.0;
205 for ( int j = 2; j <= neq; ++j ) {
206 int ih = j - 1;
207 for ( int i = 1; i <= ih; ++i ) {
208 if ( ( fabs(copy(i - 1, j - 1) ) / sum ) > tol ) {
209 ssum += fabs(copy(i - 1, j - 1) );
210 // ---- CALCULATE ROTATION ANGLE -----------------
211 double aa = atan2(copy(i - 1, j - 1) * 2.0, eval.at(i) - eval.at(j) ) / 2.0;
212 double si = sin(aa);
213 double co = cos(aa);
214 // ---- MODIFY "I" AND "J" COLUMNS OF "A" AND "V"
215 for ( int k = 1; k < i; ++k ) {
216 double tt = copy(k - 1, i - 1);
217 copy(k - 1, i - 1) = co * tt + si * copy(k - 1, j - 1);
218 copy(k - 1, j - 1) = -si * tt + co * copy(k - 1, j - 1);
219 tt = v.at(k, i);
220 v.at(k, i) = co * tt + si * v.at(k, j);
221 v.at(k, j) = -si * tt + co * v.at(k, j);
222 }
223
224 // diagonal term (i,i)
225 double tt = eval.at(i);
226 eval.at(i) = co * tt + si * copy(i - 1, j - 1);
227 double aij = -si * tt + co * copy(i - 1, j - 1);
228 tt = v.at(i, i);
229 v.at(i, i) = co * tt + si * v.at(i, j);
230 v.at(i, j) = -si * tt + co * v.at(i, j);
231
232 for ( int k = i + 1; k < j; ++k ) {
233 double tt = copy(i - 1, k - 1);
234 copy(i - 1, k - 1) = co * tt + si * copy(k - 1, j - 1);
235 copy(k - 1, j - 1) = -si * tt + co * copy(k - 1, j - 1);
236 tt = v.at(k, i);
237 v.at(k, i) = co * tt + si * v.at(k, j);
238 v.at(k, j) = -si * tt + co * v.at(k, j);
239 }
240
241 // diagonal term (j,j)
242 tt = copy(i - 1, j - 1);
243 double aji = co * tt + si * eval.at(j);
244 eval.at(j) = -si * tt + co * eval.at(j);
245
246 tt = v.at(j, i);
247 v.at(j, i) = co * tt + si * v.at(j, j);
248 v.at(j, j) = -si * tt + co * v.at(j, j);
249 //
250 for ( int k = j + 1; k <= neq; ++k ) {
251 double tt = copy(i - 1, k - 1);
252 copy(i - 1, k - 1) = co * tt + si * copy(j - 1, k - 1);
253 copy(j - 1, k - 1) = -si * tt + co * copy(j - 1, k - 1);
254 tt = v.at(k, i);
255 v.at(k, i) = co * tt + si * v.at(k, j);
256 v.at(k, j) = -si * tt + co * v.at(k, j);
257 }
258
259 // ---- MODIFY DIAGONAL TERMS --------------------
260 eval.at(i) = co * eval.at(i) + si * aji;
261 eval.at(j) = -si * aij + co * eval.at(j);
262 copy(i - 1, j - 1) = 0.0;
263 } else {
264 // ---- A(I,J) MADE ZERO BY ROTATION -------------
265 ;
266 }
267 }
268 }
269
270 // ---- CHECK FOR CONVERGENCE --------------------
271 if ( ++ite > 50 ) {
272 OOFEM_ERROR("too many iterations");
273 }
274 } while ( fabs(ssum) / sum > tol );
275 }
276
277 return { eval, v };
278 }
279
280
287 Tensor4_3d compute_dCm_dC(double m, int nf = 10)
288 {
289 auto [ eVals, eVecs ] = this->eigs(nf);
290 return compute_dCm_dC_fromEigs(m, eVals, eVecs);
291 }
292
293
300 static Tensor4_3d compute_dCm_dC_fromEigs(double m, const FloatArray &lam, const FloatMatrix &N)
301 {
302 FloatArray d(3), c(3);
303
304 c.at(1) = pow(lam.at(1), m);
305 c.at(2) = pow(lam.at(2), m);
306 c.at(3) = pow(lam.at(3), m);
307
308 d.at(1) = m * pow(lam.at(1), m - 1.);
309 d.at(2) = m * pow(lam.at(2), m - 1.);
310 d.at(3) = m * pow(lam.at(3), m - 1.);
311
312 FloatMatrix theta(3, 3);
313
314
315 // compute auxiliary variables
316 // the computation differes depends on if the eigenvalues of C are equal or not
317 if ( lam.at(1) != lam.at(2) ) {
318 if ( lam.at(2) != lam.at(3) ) {
319 if ( lam.at(1) != lam.at(3) ) {
320 // all eigenvalues are different
321 for ( int i = 1; i <= 3; i++ ) {
322 for ( int j = 1; j <= 3; j++ ) {
323 if ( i == j ) {
324 continue;
325 } else {
326 theta.at(i, j) = ( c.at(i) - c.at(j) ) / ( lam.at(i) - lam.at(j) );
327 }
328 }
329 }
330 } else { //l1 == l3 && l1 != l2
331 for ( int i = 1; i <= 3; i++ ) {
332 for ( int j = 1; j <= 3; j++ ) {
333 if ( i == j ) {
334 continue;
335 } else {
336 if ( ( i == 1 && j == 3 ) || ( i == 3 && j == 1 ) ) {
337 theta.at(i, j) = 1. / 2. * d.at(i);
338 } else {
339 theta.at(i, j) = ( c.at(i) - c.at(j) ) / ( lam.at(i) - lam.at(j) );
340 }
341 }
342 }
343 }
344 }
345 } else { //l2 == l3 && l1 != l2
346 for ( int i = 1; i <= 3; i++ ) {
347 for ( int j = 1; j <= 3; j++ ) {
348 if ( i == j ) {
349 continue;
350 } else {
351 if ( ( i == 2 && j == 3 ) || ( i == 3 && j == 2 ) ) {
352 theta.at(i, j) = 1. / 2. * d.at(i);
353 } else {
354 theta.at(i, j) = ( c.at(i) - c.at(j) ) / ( lam.at(i) - lam.at(j) );
355 }
356 }
357 }
358 }
359 }
360 } else if ( lam.at(1) != lam.at(3) ) { // l1 == l2 && l1 != l3
361 for ( int i = 1; i <= 3; i++ ) {
362 for ( int j = 1; j <= 3; j++ ) {
363 if ( i == j ) {
364 continue;
365 } else {
366 if ( ( i == 1 && j == 2 ) || ( i == 2 && j == 1 ) ) {
367 theta.at(i, j) = 1. / 2. * d.at(i);
368 } else {
369 theta.at(i, j) = ( c.at(i) - c.at(j) ) / ( lam.at(i) - lam.at(j) );
370 }
371 }
372 }
373 }
374 } else { // l1 == l2 == l3
375 for ( int i = 1; i <= 3; i++ ) {
376 for ( int j = 1; j <= 3; j++ ) {
377 theta.at(i, j) = 1. / 2. * d.at(i);
378 }
379 }
380 }
381
382
383 FloatMatrix M(9, 9);
384 std::vector< std::vector< int > >vIindex = {{ 1, 6, 5 }, { 9, 2, 4 }, { 8, 7, 3 } };
385 for ( int i = 1; i <= 3; i++ ) {
386 for ( int j = 1; j <= 3; j++ ) {
387 for ( int k = 1; k <= 3; k++ ) {
388 for ( int l = 1; l <= 3; l++ ) {
389 M.at(vIindex [ i - 1 ] [ j - 1 ], vIindex [ k - 1 ] [ l - 1 ]) = N.at(k, i) * N.at(l, j) + N.at(k, j) * N.at(l, i);
390 }
391 }
392 }
393 }
394
395 Tensor4_3d dCm_dC;
396 for ( int k = 1; k <= 3; k++ ) {
397 for ( int l = 1; l <= 3; l++ ) {
398 for ( int m = 1; m <= 3; m++ ) {
399 for ( int n = 1; n <= 3; n++ ) {
400 for ( int i = 1; i <= 3; i++ ) {
401 dCm_dC(k - 1, l - 1, m - 1, n - 1) += 0.5 * d.at(i) * N.at(k, i) * N.at(l, i) * M.at(vIindex [ i - 1 ] [ i - 1 ], vIindex [ m - 1 ] [ n - 1 ]);
402 for ( int j = 1; j <= 3; j++ ) {
403 if ( j != i ) {
404 dCm_dC(k - 1, l - 1, m - 1, n - 1) += 0.5 * theta.at(i, j) * N.at(k, i) * N.at(l, j) * M.at(vIindex [ i - 1 ] [ j - 1 ], vIindex [ m - 1 ] [ n - 1 ]);
405 }
406 }
407 }
408 }
409 }
410 }
411 }
412 return dCm_dC;
413 }
414
415
416
417
418
423 static const Tensor2_3d UnitTensor()
424 {
425 return { 1.0, 0., 0., 0., 1.0, 0., 0., 0., 1.0 };
426 }
427
428
434 {
435 Tensor2_3d cofF;
436 cofF(i_3, j_3) = 0.5 * this->compute_tensor_cross_product(* this)(i_3, j_3);
437 return cofF;
438 }
439
444 inline double compute_determinant() const
445 {
446 return ( 1. / 6. * this->compute_tensor_cross_product(* this)(m_3, n_3) * this->operator()(m_3, n_3) );
447 }
448
453 inline std::pair< double, Tensor2_3d >compute_determinant_and_cofactor() const
454 {
455 Tensor2_3d cofF;
456 cofF(i_3, j_3) = 0.5 * this->compute_tensor_cross_product(* this)(i_3, j_3);
457 auto detF = 1. / 3. * cofF(i_3, j_3) * this->operator()(i_3, j_3);
458 return { detF, cofF };
459 }
460
466 {
467 Tensor2_3d iF;
468 auto [ J, cofF ] = this->compute_determinant_and_cofactor();
469 iF(i_3, j_3) = 1. / J * cofF(j_3, i_3);
470 return iF;
471 }
472
479 {
480 Tensor2_3d C(this->operator()(1, 1) * B(2, 2) - this->operator()(1, 2) * B(2, 1) - this->operator()(2, 1) * B(1, 2) + this->operator()(2, 2) * B(1, 1), this->operator()(1, 2) * B(2, 0) - this->operator()(1, 0) * B(2, 2) + this->operator()(2, 0) * B(1, 2) - this->operator()(2, 2) * B(1, 0), this->operator()(1, 0) * B(2, 1) - this->operator()(1, 1) * B(2, 0) - this->operator()(2, 0) * B(1, 1) + this->operator()(2, 1) * B(1, 0), this->operator()(0, 2) * B(2, 1) - this->operator()(0, 1) * B(2, 2) + this->operator()(2, 1) * B(0, 2) - this->operator()(2, 2) * B(0, 1), this->operator()(0, 0) * B(2, 2) - this->operator()(0, 2) * B(2, 0) - this->operator()(2, 0) * B(0, 2) + this->operator()(2, 2) * B(0, 0), this->operator()(0, 1) * B(2, 0) - this->operator()(0, 0) * B(2, 1) + this->operator()(2, 0) * B(0, 1) - this->operator()(2, 1) * B(0, 0), this->operator()(0, 1) * B(1, 2) - this->operator()(0, 2) * B(1, 1) - this->operator()(1, 1) * B(0, 2) + this->operator()(1, 2) * B(0, 1), this->operator()(0, 2) * B(1, 0) - this->operator()(0, 0) * B(1, 2) + this->operator()(1, 0) * B(0, 2) - this->operator()(1, 2) * B(0, 0), this->operator()(0, 0) * B(1, 1) - this->operator()(0, 1) * B(1, 0) - this->operator()(1, 0) * B(0, 1) + this->operator()(1, 1) * B(0, 0) );
481 return C;
482 }
483
484
490 {
491 Tensor4_3d Ax(0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.);
492 Ax(1, 1, 0, 0) = this->operator()(2, 2);
493 Ax(1, 2, 0, 0) = -this->operator()(2, 1);
494 Ax(2, 1, 0, 0) = -this->operator()(1, 2);
495 Ax(2, 2, 0, 0) = this->operator()(1, 1);
496
497 Ax(0, 1, 1, 0) = -this->operator()(2, 2);
498 Ax(0, 2, 1, 0) = this->operator()(2, 1);
499 Ax(2, 1, 1, 0) = this->operator()(0, 2);
500 Ax(2, 2, 1, 0) = -this->operator()(0, 1);
501
502 Ax(0, 1, 2, 0) = this->operator()(1, 2);
503 Ax(0, 2, 2, 0) = -this->operator()(1, 1);
504 Ax(1, 1, 2, 0) = -this->operator()(0, 2);
505 Ax(1, 2, 2, 0) = this->operator()(0, 1);
506
507 Ax(1, 0, 0, 1) = -this->operator()(2, 2);
508 Ax(1, 2, 0, 1) = this->operator()(2, 0);
509 Ax(2, 0, 0, 1) = this->operator()(1, 2);
510 Ax(2, 2, 0, 1) = -this->operator()(1, 0);
511
512 Ax(0, 0, 1, 1) = this->operator()(2, 2);
513 Ax(0, 2, 1, 1) = -this->operator()(2, 0);
514 Ax(2, 0, 1, 1) = -this->operator()(0, 2);
515 Ax(2, 2, 1, 1) = this->operator()(0, 0);
516
517 Ax(0, 0, 2, 1) = -this->operator()(1, 2);
518 Ax(0, 2, 2, 1) = this->operator()(1, 0);
519 Ax(1, 0, 2, 1) = this->operator()(0, 2);
520 Ax(1, 2, 2, 1) = -this->operator()(0, 0);
521
522 Ax(1, 0, 0, 2) = this->operator()(2, 1);
523 Ax(1, 1, 0, 2) = -this->operator()(2, 0);
524 Ax(2, 0, 0, 2) = -this->operator()(1, 1);
525 Ax(2, 1, 0, 2) = this->operator()(1, 0);
526
527 Ax(0, 0, 1, 2) = -this->operator()(2, 1);
528 Ax(0, 1, 1, 2) = this->operator()(2, 0);
529 Ax(2, 0, 1, 2) = this->operator()(0, 1);
530 Ax(2, 1, 1, 2) = -this->operator()(0, 0);
531
532 Ax(0, 0, 2, 2) = this->operator()(1, 1);
533 Ax(0, 1, 2, 2) = -this->operator()(1, 0);
534 Ax(1, 0, 2, 2) = -this->operator()(0, 1);
535 Ax(1, 1, 2, 2) = this->operator()(0, 0);
536
537 return Ax;
538 }
539};
540
541// not used for now...
542class Tensor2sym_3d : public Tensor2_symmetric< double, 3 >
543{
544public:
545 using Tensor2_symmetric< double, 3 >::Tensor2_symmetric;
546 /* Tensor2sym_3d(const oofem::FloatArrayF<6> &array){
547 * this->data[0] = array.at(1);
548 * this->data[1] = array.at(6);
549 * this->data[2] = array.at(5);
550 * this->data[3] = array.at(6);
551 * this->data[4] = array.at(2);
552 * this->data[5] = array.at(4);
553 * this->data[6] = array.at(5);
554 * this->data[7] = array.at(4);
555 * this->data[8] = array.at(3);
556 * }
557 */
558
559
561 {
562 return {
563 this->operator()(0, 0),
564 this->operator()(1, 1),
565 this->operator()(2, 2),
566 this->operator()(1, 2),
567 this->operator()(0, 2),
568 this->operator()(0, 1)
569 };
570 }
571};
572} // end namespace oofem
#define N(a, b)
double & at(std::size_t i)
double & at(Index i)
Definition floatarray.h:202
double at(std::size_t i, std::size_t j) const
double at(std::size_t i, std::size_t j) const
Tensor2_3d computeTensorPower(double pow, int nf=10)
Definition tensor2.h:121
const FloatArrayF< 9 > to_voigt_form()
Definition tensor2.h:99
std::pair< FloatArrayF< 3 >, FloatMatrixF< 3, 3 > > eigs(int nf=15) const
Definition tensor2.h:174
Tensor4_3d compute_tensor_cross_product() const
Definition tensor2.h:489
static Tensor2_3d computeTensorPowerFromEigs(const FloatArray &eVals, const FloatMatrix &eVecs, double m)
Definition tensor2.h:135
static Tensor2_3d computeTensorPowerFromEigs(const FloatArray &eVals, const FloatMatrix &eVecs, double m, const FloatArray &coeff)
Definition tensor2.h:154
Tensor2_3d compute_inverse() const
Definition tensor2.h:465
static Tensor4_3d compute_dCm_dC_fromEigs(double m, const FloatArray &lam, const FloatMatrix &N)
Definition tensor2.h:300
Tensor4_3d compute_dCm_dC(double m, int nf=10)
Definition tensor2.h:287
static const Tensor2_3d UnitTensor()
Definition tensor2.h:423
Tensor2_3d compute_cofactor() const
Definition tensor2.h:433
double compute_determinant() const
Definition tensor2.h:444
Tensor2_3d compute_tensor_cross_product(const Tensor2_3d &B) const
Definition tensor2.h:478
std::pair< double, Tensor2_3d > compute_determinant_and_cofactor() const
Definition tensor2.h:453
Tensor2_3d(const oofem::FloatArrayF< 9 > &array)
Definition tensor2.h:83
const FloatArrayF< 6 > to_voigt_form()
Definition tensor2.h:560
#define OOFEM_ERROR(...)
Definition error.h:79
static FTensor::Index< 'j', 3 > j_3
Definition index.h:44
static FTensor::Index< 'n', 3 > n_3
Definition index.h:48
static FTensor::Index< 'i', 3 > i_3
Definition index.h:43
static FTensor::Index< 'm', 3 > m_3
Definition index.h:47
double sum(const FloatArray &x)

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