OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
strainvector.C
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 - 2013 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 "strainvector.h"
36 #include "stressvector.h"
37 #include "mathfem.h"
38 #include "floatarray.h"
39 #include "floatmatrix.h"
40 #include "error.h"
41 
42 namespace oofem {
44 { }
45 
47 { }
48 
49 void
51 {
52  MaterialMode myMode = this->giveStressStrainMode();
53 
54  if ( myMode == _1dMat ) {
55  // 1D model
56  OOFEM_ERROR("No Split for 1D!");
57  // dev.resize(1); dev.at(1) = 0.0;
58  // vol = this->at (1);
59  } else if ( myMode == _PlaneStress ) {
60  // plane stress problem
61  OOFEM_ERROR("No Split for plane stress!");
62  // dev = *this;
63  // vol = (this->at(1)+this->at(2))/2.0;
64  // dev.at(1) -= vol;
65  // dev.at(2) -= vol;
66  } else {
67  // 3d problem or plane strain problem
68  dev = * this;
69  vol = ( this->at(1) + this->at(2) + this->at(3) ) / 3.0;
70  dev.at(1) -= vol;
71  dev.at(2) -= vol;
72  dev.at(3) -= vol;
73  }
74 }
75 
76 void
78 {
79  MaterialMode myMode = this->giveStressStrainMode();
80 
81  if ( myMode == _1dMat ) {
82  // 1D model
83  OOFEM_ERROR("No sum for 1D!");
84  // dev.resize(1); dev.at(1) = 0.0;
85  // vol = this->at (1);
86  } else if ( myMode == _PlaneStress ) {
87  // plane stress problem
88  OOFEM_ERROR("No sum for plane stress!");
89  // dev = *this;
90  // vol = (this->at(1)+this->at(2))/2.0;
91  // dev.at(1) -= vol;
92  // dev.at(2) -= vol;
93  } else {
94  // 3d, plane strain or axisymmetric problem
95  answer = * this;
96  for ( int i = 0; i < 3; i++ ) {
97  answer(i) += vol;
98  }
99  }
100 }
101 
102 void
104 {
105  //
106  // This function computes sorted principal values of a strain vector.
107  // Engineering notation is used.
108  //
109 
110  MaterialMode myMode = this->giveStressStrainMode();
111  int size = this->giveSize();
112 
113  if ( myMode == _1dMat ) {
114  answer = * this;
115  } else if ( myMode == _PlaneStress ) {
116  // 2D problem
117  double ast, dst, D;
118  answer.resize(2);
119 
120  ast = this->at(1) + this->at(2);
121  dst = this->at(1) - this->at(2);
122  D = sqrt( dst * dst + this->at(3) * this->at(3) );
123  answer.at(1) = 0.5 * ( ast + D );
124  answer.at(2) = 0.5 * ( ast - D );
125  } else {
126  // 3D problem
127  double I1 = 0.0, I2 = 0.0, I3 = 0.0, s1, s2, s3;
128  FloatArray s;
129  int nonzeroFlag = 0;
130 
131  this->convertToFullForm(s);
132  for ( int i = 1; i <= size; i++ ) {
133  if ( fabs( s.at(i) ) > 1.e-20 ) {
134  nonzeroFlag = 1;
135  }
136  }
137 
138  answer.resize(3);
139  answer.zero();
140  if ( nonzeroFlag == 0 ) {
141  return;
142  }
143 
144  I1 = s.at(1) + s.at(2) + s.at(3);
145  I2 = s.at(1) * s.at(2) + s.at(2) * s.at(3) + s.at(3) * s.at(1) -
146  0.25 * ( s.at(4) * s.at(4) + s.at(5) * s.at(5) + s.at(6) * s.at(6) );
147  I3 = s.at(1) * s.at(2) * s.at(3) +
148  0.25 * ( s.at(4) * s.at(5) * s.at(6) - s.at(1) * s.at(4) * s.at(4) -
149  s.at(2) * s.at(5) * s.at(5) - s.at(3) * s.at(6) * s.at(6) );
150 
151  /*
152  * Call cubic3r to ensure, that all three real eigenvalues will be found, because we have symmetric tensor.
153  * This allows to overcome various rounding errors when solving general cubic equation.
154  */
155  int num;
156  cubic3r( ( double ) -1., I1, -I2, I3, & s1, & s2, & s3, &num);
157 
158  if (num > 0 ) {
159  answer.at(1) = s1;
160  }
161 
162  if (num > 1 ) {
163  answer.at(2) = s2;
164  }
165 
166  if (num > 2 ) {
167  answer.at(3) = s3;
168  }
169 
170  // sort results
171  for ( int i = 1; i < 3; i++ ) {
172  for ( int j = 1; j < 3; j++ ) {
173  if ( answer.at(j + 1) > answer.at(j) ) {
174  std :: swap( answer.at(j + 1), answer.at(j) );
175  }
176  }
177  }
178  }
179 }
180 
181 void
183 //
184 // This function computes the principal direction of the receiver
185 // associated with the maximum principal value.
186 //
187 {
188  FloatArray princval;
189  FloatMatrix princdir;
190  this->computePrincipalValDir(princval, princdir);
191  int n = princval.giveSize();
192  answer.resize(n);
193  for ( int i = 1; i <= n; i++ ) {
194  answer.at(i) = princdir.at(i, 1);
195  }
196 }
197 
198 void
200 {
201  //
202  // This function computes principal values & directions of the receiver.
203  //
204  // Return Values:
205  //
206  // answer -> principal strains (ordered from largest to smallest)
207  // dir -> principal strain directions
208  //
209 
210  FloatMatrix ss;
211  FloatArray sp;
212  int nval;
213  int nonzeroFlag = 0;
214  int size = this->giveSize();
215  MaterialMode myMode = this->giveStressStrainMode();
216 
217  if ( myMode == _1dMat ) {
218  // 1D problem
219  answer = * this;
220  dir.resize(1, 1);
221  dir.at(1, 1) = 1.0;
222  return;
223  } else if ( myMode == _PlaneStress ) {
224  // 2D problem
225  ss.resize(2, 2);
226  answer.resize(2);
227 
228  for ( int i = 1; i <= size; i++ ) {
229  if ( fabs( this->at(i) ) > 1.e-20 ) {
230  nonzeroFlag = 1;
231  }
232  }
233 
234  if ( nonzeroFlag == 0 ) {
235  answer.zero();
236  return;
237  }
238 
239  ss.at(1, 1) = this->at(1);
240  ss.at(2, 2) = this->at(2);
241 
242  ss.at(1, 2) = ss.at(2, 1) = 0.5 * this->at(3);
243  } else {
244  // 3D problem
245  ss.resize(3, 3);
246  FloatArray s;
247 
248  answer.resize(3);
249 
250  this->convertToFullForm(s);
251  for ( int i = 1; i <= size; i++ ) {
252  if ( fabs( s.at(i) ) > 1.e-20 ) {
253  nonzeroFlag = 1;
254  }
255  }
256 
257  if ( nonzeroFlag == 0 ) {
258  answer.zero();
259  return;
260  }
261 
262  ss.at(1, 1) = s.at(1);
263  ss.at(2, 2) = s.at(2);
264  ss.at(3, 3) = s.at(3);
265  ss.at(1, 2) = ss.at(2, 1) = 0.5 * s.at(6);
266  ss.at(1, 3) = ss.at(3, 1) = 0.5 * s.at(5);
267  ss.at(2, 3) = ss.at(3, 2) = 0.5 * s.at(4);
268  }
269 
270 #if 0
271  ss.Jacobi(& answer, & dir, & i);
272 #else
273  ss.jaco_(answer, dir, 10);
274 #endif
275  // sort results (from the largest to the smallest eigenvalue)
276  nval = 3;
277  if ( myMode == _PlaneStress ) {
278  nval = 2;
279  }
280 
281  for ( int ii = 1; ii < nval; ii++ ) {
282  for ( int jj = 1; jj < nval; jj++ ) {
283  if ( answer.at(jj + 1) > answer.at(jj) ) {
284  // swap eigenvalues and eigenvectors
285  std :: swap( answer.at(jj + 1), answer.at(jj) );
286  for ( int kk = 1; kk <= nval; kk++ ) {
287  std :: swap( dir.at(kk, jj + 1), dir.at(kk, jj) );
288  }
289  }
290  }
291  }
292 }
293 
294 void
296 {
297  printf("StrainVector (MaterialMode %d)\n", mode);
298  for ( double x : this->values ) {
299  printf("%10.3e ", x);
300  }
301 
302  printf("\n");
303 }
304 
305 
306 double
308 {
309  //
310  // This function computes the change of volume. This is different from the volumetric strain.
311  //
313  if ( myMode == _1dMat ) {
314  // 1d problem
315  return values [ 0 ];
316  } else if ( myMode == _PlaneStress ) {
317  // 2d problem: plane stress
318  return values [ 0 ] + values [ 1 ];
319  } else {
320  // plane strain, axisymmetry or full 3d
321  return values [ 0 ] + values [ 1 ] + values [ 2 ];
322  }
323 }
324 
325 double
327 {
328  //
329  // This function computes the tensorial Norm of the strain in engineering notation
330  //
332  if ( myMode == _1dMat ) {
333  // 1d problem
334  return sqrt(values [ 0 ] * values [ 0 ]);
335  } else if ( myMode == _PlaneStress ) {
336  // 2d problem: plane stress
337  return sqrt( .5 * ( 2. * values [ 0 ] * values [ 0 ] + 2 * values [ 1 ] * values [ 1 ] + values [ 2 ] * values [ 2 ] ) );
338  } else if ( myMode == _PlaneStrain ) {
339  // plane strain or axisymmetry
340  return sqrt( .5 * ( 2. * values [ 0 ] * values [ 0 ] + 2. * values [ 1 ] * values [ 1 ] + 2. * values [ 2 ] * values [ 2 ] +
341  values [ 3 ] * values [ 3 ] ) );
342  } else {
343  // 3d problem
344  return sqrt( .5 * ( 2. * values [ 0 ] * values [ 0 ] + 2. * values [ 1 ] * values [ 1 ] + 2. * values [ 2 ] * values [ 2 ] +
345  values [ 3 ] * values [ 3 ] + values [ 4 ] * values [ 4 ] + values [ 5 ] * values [ 5 ] ) );
346  }
347 }
348 
349 void
350 StrainVector :: applyElasticStiffness(StressVector &stress, const double EModulus, const double nu) const
351 {
352  //
353  // This function applies the elastic stiffness to the total strain vector
354  //
355 
357  if ( myMode == _1dMat ) {
358  stress(0) = EModulus * values [ 0 ];
359  } else if ( myMode == _PlaneStress ) {
360  double factor = EModulus / ( 1. - nu * nu );
361  stress(0) = factor * ( values [ 0 ] + nu * values [ 1 ] );
362  stress(1) = factor * ( nu * values [ 0 ] + values [ 1 ] );
363  stress(2) = factor * ( ( ( 1 - nu ) / 2. ) * values [ 2 ] );
364  } else if ( myMode == _PlaneStrain ) {
365  if ( nu >= 0.5 ) {
366  OOFEM_ERROR("nu must be less than 0.5");
367  }
368 
369  double factor = EModulus / ( ( 1. + nu ) * ( 1. - 2. * nu ) );
370  stress(0) = factor * ( ( 1. - nu ) * values [ 0 ] + nu * values [ 1 ] );
371  stress(1) = factor * ( nu * values [ 0 ] + ( 1. - nu ) * values [ 1 ] );
372  stress(2) = nu * ( stress(0) + stress(1) );
373  stress(3) = factor * ( ( ( 1. - 2. * nu ) / 2. ) * values [ 3 ] );
374  } else {
375  if ( nu >= 0.5 ) {
376  OOFEM_ERROR("nu must be less than 0.5");
377  }
378 
379  double factor = EModulus / ( ( 1. + nu ) * ( 1. - 2. * nu ) );
380  stress(0) = factor * ( ( 1. - nu ) * values [ 0 ] + nu * values [ 1 ] + nu * values [ 2 ] );
381  stress(1) = factor * ( nu * values [ 0 ] + ( 1. - nu ) * values [ 1 ] + nu * values [ 2 ] );
382  stress(2) = factor * ( nu * values [ 0 ] + nu * values [ 1 ] + ( 1. - nu ) * values [ 2 ] );
383  stress(3) = factor * ( ( ( 1. - 2. * nu ) / 2. ) * values [ 3 ] );
384  stress(4) = factor * ( ( ( 1. - 2. * nu ) / 2. ) * values [ 4 ] );
385  stress(5) = factor * ( ( ( 1. - 2. * nu ) / 2. ) * values [ 5 ] );
386  }
387 }
388 
389 void
391  const double EModulus,
392  const double nu) const
393 {
394  //
395  // This function applies the elastic stiffness to the deviatoric strain vector
396  //
397 
398  applyDeviatoricElasticStiffness( stress, EModulus / ( 2. * ( 1. + nu ) ) );
399 }
400 
401 void
403  const double GModulus) const
404 {
405  //
406  // This function applies the elastic stiffness to the deviatoric strain vector
407  //
408 
410  if ( myMode == _1dMat ) {
411  OOFEM_ERROR("No Split for 1D");
412  } else if ( myMode == _PlaneStress ) {
413  OOFEM_ERROR("No Split for Plane Stress");
414  } else if ( myMode == _PlaneStrain ) {
415  if ( stress.giveStressStrainMode() != _PlaneStrain ) {
416  stress.letStressStrainModeBe(_PlaneStrain);
417  }
418 
419  stress(0) = 2. * GModulus * values [ 0 ];
420  stress(1) = 2. * GModulus * values [ 1 ];
421  stress(2) = 2. * GModulus * values [ 2 ];
422  stress(3) = GModulus * values [ 3 ];
423  } else if ( myMode == _PlaneStrainGrad ) {
424  if ( stress.giveStressStrainMode() != _PlaneStrainGrad ) {
425  stress.letStressStrainModeBe(_PlaneStrainGrad);
426  }
427 
428  stress(0) = 2. * GModulus * values [ 0 ];
429  stress(1) = 2. * GModulus * values [ 1 ];
430  stress(2) = 2. * GModulus * values [ 2 ];
431  stress(3) = GModulus * values [ 3 ];
432  stress(4) = values [ 4 ];
433  } else {
434  if ( stress.giveStressStrainMode() != _3dMat ) {
435  stress.letStressStrainModeBe(_3dMat);
436  }
437 
438  stress(0) = 2. * GModulus * values [ 0 ];
439  stress(1) = 2. * GModulus * values [ 1 ];
440  stress(2) = 2. * GModulus * values [ 2 ];
441  stress(3) = GModulus * values [ 3 ];
442  stress(4) = GModulus * values [ 4 ];
443  stress(5) = GModulus * values [ 5 ];
444  }
445 }
446 
447 
448 
449 void
451  const FloatMatrix &base,
452  int transpose) const
453 //
454 // returns transformation matrix for 3d - strains to another system of axes,
455 // given by base.
456 // In base (FloatMatrix[3,3]) there are on each column stored vectors of
457 // coordinate system to which we do transformation.
458 //
459 // If transpose == 1 we transpose base matrix before transforming
460 //
461 {
462  FloatMatrix t;
463  answer.resize(6, 6);
464  answer.zero();
465 
466  if ( transpose == 1 ) {
467  t.beTranspositionOf(base);
468  } else {
469  t = base;
470  }
471 
472  answer.at(1, 1) = t.at(1, 1) * t.at(1, 1);
473  answer.at(1, 2) = t.at(2, 1) * t.at(2, 1);
474  answer.at(1, 3) = t.at(3, 1) * t.at(3, 1);
475  answer.at(1, 4) = t.at(2, 1) * t.at(3, 1);
476  answer.at(1, 5) = t.at(1, 1) * t.at(3, 1);
477  answer.at(1, 6) = t.at(1, 1) * t.at(2, 1);
478 
479  answer.at(2, 1) = t.at(1, 2) * t.at(1, 2);
480  answer.at(2, 2) = t.at(2, 2) * t.at(2, 2);
481  answer.at(2, 3) = t.at(3, 2) * t.at(3, 2);
482  answer.at(2, 4) = t.at(2, 2) * t.at(3, 2);
483  answer.at(2, 5) = t.at(1, 2) * t.at(3, 2);
484  answer.at(2, 6) = t.at(1, 2) * t.at(2, 2);
485 
486  answer.at(3, 1) = t.at(1, 3) * t.at(1, 3);
487  answer.at(3, 2) = t.at(2, 3) * t.at(2, 3);
488  answer.at(3, 3) = t.at(3, 3) * t.at(3, 3);
489  answer.at(3, 4) = t.at(2, 3) * t.at(3, 3);
490  answer.at(3, 5) = t.at(1, 3) * t.at(3, 3);
491  answer.at(3, 6) = t.at(1, 3) * t.at(2, 3);
492 
493  answer.at(4, 1) = 2.0 * t.at(1, 2) * t.at(1, 3);
494  answer.at(4, 2) = 2.0 * t.at(2, 2) * t.at(2, 3);
495  answer.at(4, 3) = 2.0 * t.at(3, 2) * t.at(3, 3);
496  answer.at(4, 4) = ( t.at(2, 2) * t.at(3, 3) + t.at(3, 2) * t.at(2, 3) );
497  answer.at(4, 5) = ( t.at(1, 2) * t.at(3, 3) + t.at(3, 2) * t.at(1, 3) );
498  answer.at(4, 6) = ( t.at(1, 2) * t.at(2, 3) + t.at(2, 2) * t.at(1, 3) );
499 
500  answer.at(5, 1) = 2.0 * t.at(1, 1) * t.at(1, 3);
501  answer.at(5, 2) = 2.0 * t.at(2, 1) * t.at(2, 3);
502  answer.at(5, 3) = 2.0 * t.at(3, 1) * t.at(3, 3);
503  answer.at(5, 4) = ( t.at(2, 1) * t.at(3, 3) + t.at(3, 1) * t.at(2, 3) );
504  answer.at(5, 5) = ( t.at(1, 1) * t.at(3, 3) + t.at(3, 1) * t.at(1, 3) );
505  answer.at(5, 6) = ( t.at(1, 1) * t.at(2, 3) + t.at(2, 1) * t.at(1, 3) );
506 
507  answer.at(6, 1) = 2.0 * t.at(1, 1) * t.at(1, 2);
508  answer.at(6, 2) = 2.0 * t.at(2, 1) * t.at(2, 2);
509  answer.at(6, 3) = 2.0 * t.at(3, 1) * t.at(3, 2);
510  answer.at(6, 4) = ( t.at(2, 1) * t.at(3, 2) + t.at(3, 1) * t.at(2, 2) );
511  answer.at(6, 5) = ( t.at(1, 1) * t.at(3, 2) + t.at(3, 1) * t.at(1, 2) );
512  answer.at(6, 6) = ( t.at(1, 1) * t.at(2, 2) + t.at(2, 1) * t.at(1, 2) );
513 }
514 } // end namespace oofem
void applyElasticStiffness(StressVector &stress, const double EModulus, const double nu) const
Applies the elastic stiffness to the strain.
Definition: strainvector.C:350
void computeDeviatoricVolumetricSplit(StrainVector &answer, double &vol) const
Computes split of receiver into deviatoric and volumetric part.
Definition: strainvector.C:50
void computeMaxPrincipalDir(FloatArray &answer) const
Computes the principal direction of the receiver associated with the maximum principal value...
Definition: strainvector.C:182
std::vector< double > values
Stored values.
Definition: floatarray.h:86
Specialization of a floating point array for representing a stress state.
Definition: stressvector.h:48
MaterialMode giveStressStrainMode() const
Returns the material mode of receiver.
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
void giveTranformationMtrx(FloatMatrix &answer, const FloatMatrix &base, int transpose=0) const
Computes 3d transformation matrix from standard vector transformation matrix.
Definition: strainvector.C:450
void convertToFullForm(FloatArray &fullform) const
Computes the full form of receiver.
void computePrincipalValDir(FloatArray &answer, FloatMatrix &dir) const
Computes the principal values and principal directions of the receiver.
Definition: strainvector.C:199
StressStrainMatMode mode
Stress strain mode.
Specialization of a floating point array for representing a strain state.
Definition: strainvector.h:45
void applyDeviatoricElasticStiffness(StressVector &stress, const double EModulus, const double nu) const
Applies the elastic stiffness to the deviatoric strain.
Definition: strainvector.C:390
MaterialMode
Type representing material mode of integration point.
Definition: materialmode.h:89
Base class for stress/strain vector representations.
bool jaco_(FloatArray &eval, FloatMatrix &v, int nf)
Computes eigenvalues and eigenvectors of receiver (must be symmetric) The receiver is preserved...
Definition: floatmatrix.C:1912
void printYourself() const
Prints receiver on stdout, useful for debugging.
Definition: strainvector.C:295
void cubic3r(double a, double b, double c, double d, double *r1, double *r2, double *r3, int *num)
Solves cubic equation for real roots, assuming that if cubic polynomial given then the only possibili...
Definition: mathfem.C:155
#define OOFEM_ERROR(...)
Definition: error.h:61
StrainVector(MaterialMode)
Constructor. Creates zero value stress/strain vector for given material mode.
Definition: strainvector.C:43
double at(int i, int j) const
Coefficient access function.
Definition: floatmatrix.h:176
Class representing vector of real numbers.
Definition: floatarray.h:82
Implementation of matrix containing floating point numbers.
Definition: floatmatrix.h:94
void resize(int rows, int cols)
Checks size of receiver towards requested bounds.
Definition: floatmatrix.C:1358
void zero()
Zeroes all coefficients of receiver.
Definition: floatarray.C:658
void beTranspositionOf(const FloatMatrix &src)
Assigns to the receiver the transposition of parameter.
Definition: floatmatrix.C:323
void computeDeviatoricVolumetricSum(StrainVector &answer, const double vol) const
Computes sum of deviatoric and volumetric part.
Definition: strainvector.C:77
double computeStrainNorm() const
Computes the tensorial norm of the strain in engineering notation.
Definition: strainvector.C:326
void computePrincipalValues(FloatArray &answer) const
Computes the principal values of the receiver.
Definition: strainvector.C:103
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
the oofem namespace is to define a context or scope in which all oofem names are defined.
void letStressStrainModeBe(const MaterialMode newMode)
Changes the material mode of receiver.
double computeVolumeChange() const
Computes the change of volume.
Definition: strainvector.C:307
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:31 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011