High Performance Plasticity  0.5.0
continuum.h
Go to the documentation of this file.
1 #ifndef HPP_CONTINUUM_H
5 #define HPP_CONTINUUM_H
6 
7 #include <hpp/config.h>
8 #include <hpp/tensor.h>
9 
10 // Units
11 // Quantities are in GPA
12 #define GPA (1.0)
13 #define MPA (1e-3)
14 #define KPA (1e-6)
15 #define PA (1e-9)
16 
17 namespace hpp
18 {
19 
20 template <typename U>
21 Tensor2<U> deformationGradFromVelGrad(U t_init, const Tensor2<U>& F_init, const Tensor2<U>& L, U t) {
22  U dt = t - t_init;
23  Tensor2<U> F = ((dt*L).exp())*F_init;
24  return F;
25 }
26 
27 template <typename U>
29  // D components
30  std::vector<U> D_comps(3);
31  D_comps[0] = std::sqrt(2.0/3.0)*std::cos(theta-M_PI/3.0);
32  D_comps[1] = std::sqrt(2.0/3.0)*std::cos(theta+M_PI/3.0);
33  D_comps[2] = -std::sqrt(2.0/3.0)*std::cos(theta);
34 
35  // Standard basis
36  std::vector<std::vector<U>> basis(3);
37  for (int i=0; i<3; i++) {
38  basis[i] = std::vector<U>(3);
39  basis[i][i] = 1.0;
40  }
41 
42  // Construct D_0
43  Tensor2<U> D_0(3,3);
44  for (int i=0; i<3; i++) {
45  std::vector<U> e_i = basis[i];
46  D_0 += D_comps[i]*outer(e_i, e_i);
47  }
48  Tensor2<U> D = eDot*D_0;
49 
50  // Return
51  return D;
52 }
53 
54 template <typename T>
56  T theta;
57  T DNorm;
59 };
60 
66 template <typename T>
68  // The decomposition
70 
71  // Stretching tensor from velocity gradient
72  Tensor2<T> D = ((T)0.5)*(L + L.trans());
73 
74  // Evec decomposition of D
75  std::valarray<T> Devals;
76  D.evecDecomposition(Devals, decomp.evecs);
77 
78  // Ensure that the determinant of the eigenvector matrix is positive
79  // for the purposes of treating it like a rotation
80  if (decomp.evecs.det() < 0) {
81  std::swap(Devals[0], Devals[1]);
82  for (int i=0; i<3; i++) {
83  std::swap(decomp.evecs(i,0), decomp.evecs(i,1));
84  }
85  }
86  if (!decomp.evecs.isRotationMatrix()) {
87  Tensor2<T> product = decomp.evecs*decomp.evecs.trans();
88  std::cerr << "R*R^T = " << product << std::endl;
89  throw std::runtime_error("The transformation to the stretching tensor frame is not a rotation.");
90  }
91 
92  // D in its principal frame
93  Tensor2<T> DPrincipal(3,3);
94  for (int i=0; i<3; i++) {
95  DPrincipal(i,i) = Devals[i];
96  }
97 
98  // Norm out strain rate
99  decomp.DNorm = DPrincipal.frobeniusNorm();
100 
101  // Components of D_0 decomposition
102  std::valarray<T> D0evals = Devals/decomp.DNorm;
103  T D0evalsMag = 0.0;
104  for (unsigned int i=0; i<D0evals.size(); i++) {
105  D0evalsMag += std::pow(D0evals[i],2.0);
106  }
107  D0evalsMag = std::sqrt(D0evalsMag);
108  D0evals /= D0evalsMag;
109  T E1 = D0evals[0]/std::sqrt(2.0/3.0);
110  T E2 = D0evals[1]/std::sqrt(2.0/3.0);
111  T E3 = D0evals[2]/std::sqrt(2.0/3.0);
112 
113  // Solve for the angle theta
114  T theta1 = std::acos(-E3);
115  T theta2 = 2.0*M_PI - std::acos(-E3);
116  T theta3 = std::acos(E1) + M_PI/3.0;
117  //T theta4 = 7.0*M_PI/3.0 - std::acos(E1); //Not needed, but here for completeness
118  T theta5 = std::acos(E2) - M_PI/3.0;
119  T theta6 = 5.0*M_PI/3.0 - std::acos(E2);
120 
121  // Get the matching theta
122  T theta;
123  T equiv = std::numeric_limits<T>::epsilon()*10000.0;
124  if (std::abs(theta1-theta3)<equiv) {
125  theta = theta1;
126  }
127  else {
128  theta = theta2;
129  }
130 
131  // Verify
132  T minError = std::min(std::abs(theta-theta5), std::abs(theta-theta6));
133  if (minError > equiv) {
134  std::string errorMsg = std::string("Could not correctly determine theta. Error = ");
135  errorMsg += std::to_string(minError);
136  throw std::runtime_error(errorMsg);
137  }
138 
139  // Return
140  decomp.theta = theta;
141  return decomp;
142 }
143 
150 template <typename U>
152  Tensor4<U> L(3,3,3,3);
153  L = 2*mu*identityTensor4<U>(3) ;
154  L += ((U)(kappa-(2.0/3)*mu))*outer<U>(identityTensor2<U>(3), identityTensor2<U>(3));
155  return L;
156 }
157 
165 template <typename U>
167  Tensor4<U> L(3,3,3,3);
168  U cbar = c11-c12-2*c44;
169  for (int i=0; i<3; i++) {
170  for (int j=0; j<3; j++) {
171  for (int k=0; k<3; k++) {
172  for (int l=0; l<3; l++) {
173  L(i,j,k,l) = c12*(i==j)*(k==l);
174  L(i,j,k,l) += c44*((i==k)*(j==l)+(i==l)*(j==k));
175  for (int r=0; r<3; r++) {
176  L(i,j,k,l) += cbar*(i==r)*(j==r)*(k==r)*(l==r);
177  }
178  }
179  }
180  }
181  }
182  return L;
183 }
184 
191 template <typename U>
192 Tensor4<U> volumeAverage(const std::vector<Tensor4<U>>& tVec, const std::vector<U>& vVec) {
193  // Check sizes
194  unsigned int nT = tVec.size();
195  unsigned int nV = vVec.size();
196  if (nT != nV) {
197  throw std::runtime_error("Different number of stiffness tensors and volumes.");
198  }
199 
200  // Sum up
201  Tensor4<U> tTot = tVec[0];
202  U vTot = vVec[0];
203  for (unsigned int i=1; i<nT; i++) {
204  tTot += tVec[i];
205  vTot += vVec[i];
206  }
207 
208  // Average
209  Tensor4<U> tAvg = tTot/vTot;
210  return tAvg;
211 }
212 
213 template <typename U>
214 Tensor4<U> getEshelbyTensorCubicMaterialSphericalInclusion(U c11, U c12, U c44, U I0, U I1, U I2) {
215  U mu = c11 - c12 - 2.0*c44;
216  U a = mu*(c11+c12)/(c11*c44);
217  U b = std::pow(mu, 2.0)*(c11+2*c12+c44)/(c11*std::pow(c44,2.0));
218  U m = c11-c44;
219  U p = c12+c44;
220 
221  // Construct E
222  Tensor4<U> A0(3,3,3,3);
223  Tensor4<U> A1(3,3,3,3);
224  Tensor4<U> A2(3,3,3,3);
225  A0(0,0,0,0) = (1.0/3.0)*c11;
226  A1(0,0,0,0) = (2*m/3.0)*c11*c44;
227  A2(0,0,0,0) = a/c44;
228  A0(0,0,1,1) = 0.0;
229  A1(0,0,1,1) = -(p/3.0)*c11*c44;
230  A2(0,0,1,1) = -p*mu/(c11*std::pow(c44,2.0));
231  A0(0,1,0,1) = (1.0/6.0)*c44;
232  A1(0,1,0,1) = a*(mu-2.0*c44)/(12.0*mu*c44);
233  A2(0,1,0,1) = (1.0/2.0)*(a/(2.0*c44)-b/mu);
234  Tensor4<U> E = I0*A0+I1*A1+I2*A2;
235 
236 
237 
238  // Note that S has the both minor symmetries S_{ijkl} = S{jikl} = S{ijlk}
239  // Here we apply leading minor symmetry to E before using it to construct S
240  E(1,0,0,1) = E(0,1,0,1);
241 
242  // EXPERIMENT
243  E(0,1,1,0) = E(0,1,0,1);
244 
245  std::cout << "E = " << E << std::endl;
246 
247  // Construct S
248  Tensor4<U> C = cubeSymmetricElasticityTensor(c11, c12, c44);
249 
250  std::cout << "C = " << C << std::endl;
251 
252  Tensor4<U> S = contract(C, E);
253 
254  // Return
255  return S;
256 }
257 
264 template <typename U>
265 Tensor4<U> getHomogenizedStiffnessVolumeAverage(const std::vector<Tensor4<U>>& cVec, const std::vector<U>& vVec) {
266  // Check sizes
267  unsigned int nC = cVec.size();
268  unsigned int nV = vVec.size();
269  if (nC != nV) {
270  throw std::runtime_error("Different number of stiffness tensors and volumes.");
271  }
272 
273  // Get volume average
274  Tensor4<U> cTot = (U)0.0*cVec[0];
275  U vTot = 0.0;
276  for (unsigned int i=0; i<cVec.size(); i++) {
277  cTot += cVec[i]*vVec[i];
278  vTot += vVec[i];
279  }
280  Tensor4<U> cBar = cTot/vTot;
281  return cBar;
282 }
283 
291 template <typename U>
292 Tensor4<U> getHomogenizedStiffnessELSC(const std::vector<Tensor4<U>>& cVec, const std::vector<U>& vVec, const Tensor4<U>& S) {
293  // Check sizes
294  unsigned int nC = cVec.size();
295  unsigned int nV = vVec.size();
296  if (nC != nV) {
297  throw std::runtime_error("Different number of stiffness tensors and volumes.");
298  }
299 
300  // Convergence criterion
301  U cTol = 1.0e2*std::numeric_limits<U>::epsilon();
302  int maxIters = 100;
303 
304  // Initialize
305  Tensor4<U> cBar = volumeAverage(cVec, vVec);
306  U vTot = 0.0;
307  for (const auto& v : vVec) {
308  vTot += v;
309  }
310 
311  // Common terms
312  Tensor4<U> SInv = S.inv();
313 
314  // Single allocations for frequent terms
315  Tensor4<U> Ar = (U)0.0*cBar;
316  Tensor4<U> cBarTot = (U)0.0*cBar;
317  Tensor4<U> cBarPrev = (U)0.0*cBar;
318  Tensor4<U> cTilde = (U)0.0*cBar;
319  Tensor4<U> cDiff = (U)0.0*cBar;
320 
321  // Iterate
322  bool converged = false;
323  for (unsigned int i=0; i<maxIters; i++) {
324  // Previous
325  cBarPrev = cBar;
326 
327  // Common terms
328  cTilde = contract(contract(cBarPrev, SInv), identityTensor4<U>(3)-S);
329 
330  // Volume average of ELSC update terms
331  cBarTot = (U)0.0*cBar;
332  for (unsigned int r=0; r<nC; r++) {
333  Ar = contract((cVec[r]+cTilde).inv(), cBarPrev+cTilde);
334  cBarTot += contract(cVec[r], Ar)*vVec[r];
335  }
336  cBar = cBarTot/vTot;
337 
338  // Check convergence
339  cDiff = cBar-cBarPrev;
340  U relDiff = cDiff.frobeniusNorm()/cBar.frobeniusNorm();
341  if (relDiff < cTol) {
342  converged = true;
343  break;
344  }
345  }
346 
347  if (!converged) {
348  throw std::runtime_error("ELSC homogenization failed to converge.");
349  }
350 
351  // Return
352  return cBar;
353 }
354 
355 } //END NAMESPACE HPP
356 
357 #endif /* HPP_CONTINUUM_H */
T frobeniusNorm() const
Definition: tensor.cpp:776
Tensor2< T > outer(const std::vector< T > &A, const std::vector< T > &B)
Definition: tensor.h:640
Definition: casesUtils.cpp:4
Tensor4< U > volumeAverage(const std::vector< Tensor4< U >> &tVec, const std::vector< U > &vVec)
Volume average fourth order tensors.
Definition: continuum.h:192
T frobeniusNorm() const
Definition: tensor.cpp:1005
Tensor2< U > deformationGradFromVelGrad(U t_init, const Tensor2< U > &F_init, const Tensor2< U > &L, U t)
Definition: continuum.h:21
T theta
Definition: continuum.h:56
Header file for tensor classes.
Definition: continuum.h:55
void evecDecomposition(std::valarray< T > &evals, Tensor2< T > &evecs)
Definition: tensor.cpp:707
Tensor4< U > getHomogenizedStiffnessELSC(const std::vector< Tensor4< U >> &cVec, const std::vector< U > &vVec, const Tensor4< U > &S)
Get the homogenized stiffness tensor using the elastic self-consistent method.
Definition: continuum.h:292
std::vector< T > abs(const std::vector< T > &vec)
Definition: tensor.h:89
T DNorm
Definition: continuum.h:57
T contract(const Tensor2< T > &A, const Tensor2< T > &B)
Definition: tensor.h:950
Tensor2< T > trans() const
The transpose of the tensor.
Definition: tensor.cpp:536
Tensor4< U > getHomogenizedStiffnessVolumeAverage(const std::vector< Tensor4< U >> &cVec, const std::vector< U > &vVec)
Get the homogenized stiffness tensor using a volume average.
Definition: continuum.h:265
Tensor4< U > cubeSymmetricElasticityTensor(U c11, U c12, U c44)
Construct a fourth order elasticity tensor accounting for cubic symmetry.
Definition: continuum.h:166
Tensor2< T > evecs
Definition: continuum.h:58
Tensor4< U > isotropicElasticityTensor(U mu, U kappa)
Construct a fourth order isotropic elasticity tensor.
Definition: continuum.h:151
Tensor2< U > stretchingVelocityGradient(U theta, U eDot)
Definition: continuum.h:28
T min(const std::vector< T > &vec)
Definition: tensor.h:98
Tensor4< T > inv() const
Definition: tensor.cpp:998
Tensor4< U > getEshelbyTensorCubicMaterialSphericalInclusion(U c11, U c12, U c44, U I0, U I1, U I2)
Definition: continuum.h:214
StretchingTensorDecomposition< T > getStretchingTensorDecomposition(const Tensor2< T > &L)
Definition: continuum.h:67