00001
00002
00003
00004
00005
00006
00007 #include "Teuchos_TestForException.hpp"
00008 #include "Phalanx_DataLayout.hpp"
00009
00010 #include "Intrepid_FunctionSpaceTools.hpp"
00011 #include "LocalNonlinearSolver.hpp"
00012
00013 namespace LCM {
00014
00015
00016 template<typename EvalT, typename Traits>
00017 J2Stress<EvalT, Traits>::
00018 J2Stress(const Teuchos::ParameterList& p) :
00019 defgrad (p.get<std::string> ("DefGrad Name"),
00020 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Tensor Data Layout") ),
00021 J (p.get<std::string> ("DetDefGrad Name"),
00022 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Scalar Data Layout") ),
00023 elasticModulus (p.get<std::string> ("Elastic Modulus Name"),
00024 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Scalar Data Layout") ),
00025 poissonsRatio (p.get<std::string> ("Poissons Ratio Name"),
00026 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Scalar Data Layout") ),
00027 yieldStrength (p.get<std::string> ("Yield Strength Name"),
00028 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Scalar Data Layout") ),
00029 hardeningModulus (p.get<std::string> ("Hardening Modulus Name"),
00030 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Scalar Data Layout") ),
00031 satMod (p.get<std::string> ("Saturation Modulus Name"),
00032 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Scalar Data Layout") ),
00033 satExp (p.get<std::string> ("Saturation Exponent Name"),
00034 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Scalar Data Layout") ),
00035 stress (p.get<std::string> ("Stress Name"),
00036 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Tensor Data Layout") ),
00037 Fp (p.get<std::string> ("Fp Name"),
00038 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Tensor Data Layout") ),
00039 eqps (p.get<std::string> ("Eqps Name"),
00040 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Scalar Data Layout") )
00041 {
00042
00043 Teuchos::RCP<PHX::DataLayout> tensor_dl =
00044 p.get< Teuchos::RCP<PHX::DataLayout> >("QP Tensor Data Layout");
00045 std::vector<PHX::DataLayout::size_type> dims;
00046 tensor_dl->dimensions(dims);
00047 numQPs = dims[1];
00048 numDims = dims[2];
00049 worksetSize = dims[0];
00050
00051 this->addDependentField(defgrad);
00052 this->addDependentField(J);
00053 this->addDependentField(elasticModulus);
00054 this->addDependentField(poissonsRatio);
00055 this->addDependentField(yieldStrength);
00056 this->addDependentField(hardeningModulus);
00057 this->addDependentField(satMod);
00058 this->addDependentField(satExp);
00059
00060
00061
00062 fpName = p.get<std::string>("Fp Name")+"_old";
00063 eqpsName = p.get<std::string>("Eqps Name")+"_old";
00064 this->addEvaluatedField(stress);
00065 this->addEvaluatedField(Fp);
00066 this->addEvaluatedField(eqps);
00067
00068
00069 be.resize(numDims, numDims);
00070 s.resize(numDims, numDims);
00071 N.resize(numDims, numDims);
00072 A.resize(numDims, numDims);
00073 expA.resize(numDims, numDims);
00074 Fpinv.resize(worksetSize, numQPs, numDims, numDims);
00075 FpinvT.resize(worksetSize, numQPs, numDims, numDims);
00076 Cpinv.resize(worksetSize, numQPs, numDims, numDims);
00077 tmp.resize(numDims, numDims);
00078 tmp2.resize(numDims, numDims);
00079
00080 this->setName("J2 Stress"+PHX::TypeString<EvalT>::value);
00081
00082 }
00083
00084
00085 template<typename EvalT, typename Traits>
00086 void J2Stress<EvalT, Traits>::
00087 postRegistrationSetup(typename Traits::SetupData d,
00088 PHX::FieldManager<Traits>& fm)
00089 {
00090 this->utils.setFieldData(stress,fm);
00091 this->utils.setFieldData(defgrad,fm);
00092 this->utils.setFieldData(J,fm);
00093 this->utils.setFieldData(elasticModulus,fm);
00094 this->utils.setFieldData(hardeningModulus,fm);
00095 this->utils.setFieldData(yieldStrength,fm);
00096 this->utils.setFieldData(satMod,fm);
00097 this->utils.setFieldData(satExp,fm);
00098 this->utils.setFieldData(Fp,fm);
00099 this->utils.setFieldData(eqps,fm);
00100 if (numDims>1) this->utils.setFieldData(poissonsRatio,fm);
00101 }
00102
00103
00104 template<typename EvalT, typename Traits>
00105 void J2Stress<EvalT, Traits>::
00106 evaluateFields(typename Traits::EvalData workset)
00107 {
00108 typedef Intrepid::FunctionSpaceTools FST;
00109 typedef Intrepid::RealSpaceTools<ScalarT> RST;
00110
00111 bool print = false;
00112
00113 std::cout.precision(15);
00114
00115 if(print) std::cout << "========= J2 STRESS_DEF ============= " << std::endl;
00116
00117 ScalarT kappa;
00118 ScalarT mu, mubar;
00119 ScalarT K, Y, siginf, delta;
00120 ScalarT Jm23;
00121 ScalarT trace;
00122 ScalarT smag2, smag, f, p, dgam;
00123 ScalarT sq23 = std::sqrt(2./3.);
00124
00125 Albany::MDArray Fpold = (*workset.stateArrayPtr)[fpName];
00126 Albany::MDArray eqpsold = (*workset.stateArrayPtr)[eqpsName];
00127
00128
00129
00130
00131 RST::inverse(Fpinv, Fpold);
00132 RST::transpose(FpinvT, Fpinv);
00133 FST::tensorMultiplyDataData<ScalarT>(Cpinv, Fpinv, FpinvT);
00134
00135 for (std::size_t cell=0; cell < workset.numCells; ++cell)
00136 {
00137 for (std::size_t qp=0; qp < numQPs; ++qp)
00138 {
00139
00140 if(print) std::cout << "defgrad tensor at cell " << cell
00141 << ", quadrature point " << qp << ":" << std::endl;
00142 if(print) std::cout << " " << defgrad(cell, qp, 0, 0);
00143 if(print) std::cout << " " << defgrad(cell, qp, 0, 1);
00144 if(print) std::cout << " " << defgrad(cell, qp, 0, 2) << std::endl;
00145 if(print) std::cout << " " << defgrad(cell, qp, 1, 0);
00146 if(print) std::cout << " " << defgrad(cell, qp, 1, 1);
00147 if(print) std::cout << " " << defgrad(cell, qp, 1, 2) << std::endl;
00148 if(print) std::cout << " " << defgrad(cell, qp, 2, 0);
00149 if(print) std::cout << " " << defgrad(cell, qp, 2, 1);
00150 if(print) std::cout << " " << defgrad(cell, qp, 2, 2) << std::endl;
00151
00152
00153 kappa = elasticModulus(cell,qp)/(3. * (1. - 2. * poissonsRatio(cell,qp)));
00154 mu = elasticModulus(cell,qp)/(2. * (1. + poissonsRatio(cell,qp)));
00155 K = hardeningModulus(cell,qp);
00156 Y = yieldStrength(cell,qp);
00157 siginf = satMod(cell,qp);
00158 delta = satExp(cell,qp);
00159 Jm23 = std::pow( J(cell,qp), -2./3. );
00160
00161
00162
00163
00164
00165
00166 if(print) std::cout << "J : " << J(cell,qp) << std::endl;
00167 if(print) std::cout << "Jm23 : " << Jm23 << std::endl;
00168
00169
00170 be.initialize(0.0);
00171
00172 for (std::size_t i=0; i < numDims; ++i)
00173 {
00174 for (std::size_t j=0; j < numDims; ++j)
00175 {
00176 for (std::size_t p=0; p < numDims; ++p)
00177 {
00178 for (std::size_t q=0; q < numDims; ++q)
00179 {
00180 be(i,j) += Jm23 * defgrad(cell,qp,i,p)
00181 * Cpinv(cell,qp,p,q) * defgrad(cell,qp,j,q);
00182 }
00183 }
00184 }
00185 }
00186
00187 trace = 0.0;
00188 for (std::size_t i=0; i < numDims; ++i)
00189 trace += be(i,i);
00190 trace /= numDims;
00191 mubar = trace*mu;
00192 for (std::size_t i=0; i < numDims; ++i)
00193 {
00194 for (std::size_t j=0; j < numDims; ++j)
00195 {
00196 s(i,j) = mu * be(i,j);
00197 }
00198 s(i,i) -= mu * trace;
00199 }
00200
00201
00202
00203 smag2 = 0.0; smag = 0.0;
00204 for (std::size_t i=0; i < numDims; ++i)
00205 for (std::size_t j=0; j < numDims; ++j)
00206 smag2 += s(i,j) * s(i,j);
00207
00208 if ( Sacado::ScalarValue<ScalarT>::eval(smag2) > 0.0 )
00209 smag = std::sqrt(smag2);
00210
00211 f = smag - sq23 * ( Y + K * eqpsold(cell,qp)
00212 + siginf * ( 1. - exp( -delta * eqpsold(cell,qp) ) ) );
00213
00214 if(print) std::cout << "smag : " << smag << std::endl;
00215 if(print) std::cout << "eqpsold: " << eqpsold(cell,qp) << std::endl;
00216 if(print) std::cout << "K : " << K << std::endl;
00217 if(print) std::cout << "Y : " << Y << std::endl;
00218 if(print) std::cout << "f : " << f << std::endl;
00219
00220 if (f > 1E-12)
00221 {
00222
00223 bool converged = false;
00224 ScalarT g = f;
00225 ScalarT H = K * eqpsold(cell,qp)
00226 + siginf*(1. - exp(-delta * eqpsold(cell,qp) ) );
00227 ScalarT H2 = 0.0;
00228 ScalarT dg = ( -2. * mubar ) * ( 1. + H / ( 3. * mubar ) );
00229 ScalarT dH = 0.0;
00230 ScalarT dH2 = 0.0;
00231 ScalarT alpha = 0.0;
00232 ScalarT alpha2 = 0.0;
00233 ScalarT res = 0.0;
00234 int count = 0;
00235 dgam = 0.0;
00236
00237 LocalNonlinearSolver<EvalT, Traits> solver;
00238
00239 std::vector<ScalarT> F(1);
00240 std::vector<ScalarT> dFdX(1);
00241 std::vector<ScalarT> X(1);
00242
00243 F[0] = f;
00244 X[0] = 0.0;
00245 dFdX[0] = ( -2. * mubar ) * ( 1. + H / ( 3. * mubar ) );
00246 while (!converged && count < 30)
00247 {
00248 count++;
00249
00250
00251
00252 solver.solve(dFdX,X,F);
00253
00254
00255
00256
00257 ScalarT X0 = X[0];
00258 alpha2 = eqpsold(cell, qp) + sq23 * X0;
00259
00260
00261
00262
00263 H2 = K * alpha2 + siginf*( 1. - exp( -delta * alpha2 ) );
00264 dH2 = K + delta * siginf * exp( -delta * alpha2 );
00265
00266
00267
00268
00269 F[0] = smag - ( 2. * mubar * X0 + sq23 * ( Y + H2 ) );
00270 dFdX[0] = -2. * mubar * ( 1. + dH2 / ( 3. * mubar ) );
00271
00272 res = std::abs(F[0]);
00273 if ( res < 1.e-11 || res/f < 1.E-11 )
00274 converged = true;
00275
00276 TEUCHOS_TEST_FOR_EXCEPTION( count > 30, std::runtime_error,
00277 std::endl << "Error in return mapping, count = " << count <<
00278 "\nres = " << res <<
00279 "\nrelres = " << res/f <<
00280 "\ng = " << F[0] <<
00281 "\ndg = " << dFdX[0] <<
00282 "\nalpha = " << alpha2 << std::endl);
00283
00284 }
00285
00286 solver.computeFadInfo(dFdX,X,F);
00287
00288 dgam = X[0];
00289
00290
00291 for (std::size_t i=0; i < numDims; ++i)
00292 for (std::size_t j=0; j < numDims; ++j)
00293 N(i,j) = (1/smag) * s(i,j);
00294
00295 for (std::size_t i=0; i < numDims; ++i)
00296 for (std::size_t j=0; j < numDims; ++j)
00297 s(i,j) -= 2. * mubar * dgam * N(i,j);
00298
00299
00300
00301 eqps(cell,qp) = alpha2;
00302
00303
00304 for (std::size_t i=0; i < numDims; ++i)
00305 for (std::size_t j=0; j < numDims; ++j)
00306 A(i,j) = dgam * N(i,j);
00307
00308 exponential_map(expA, A);
00309
00310
00311
00312
00313
00314
00315
00316 for (std::size_t i=0; i < numDims; ++i)
00317 {
00318 for (std::size_t j=0; j < numDims; ++j)
00319 {
00320 Fp(cell,qp,i,j) = 0.0;
00321 for (std::size_t p=0; p < numDims; ++p)
00322 {
00323 Fp(cell,qp,i,j) += expA(i,p) * Fpold(cell,qp,p,j);
00324 }
00325 }
00326 }
00327 }
00328 else
00329 {
00330
00331 eqps(cell, qp) = eqpsold(cell,qp);
00332 for (std::size_t i=0; i < numDims; ++i)
00333 for (std::size_t j=0; j < numDims; ++j)
00334 Fp(cell,qp,i,j) = Fpold(cell,qp,i,j);
00335 }
00336
00337 if(print) std::cout << "after, eqps: " << eqps(cell, qp) << std::endl;;
00338
00339
00340
00341 p = 0.5 * kappa * ( J(cell,qp) - 1 / ( J(cell,qp) ) );
00342
00343
00344 for (std::size_t i=0; i < numDims; ++i)
00345 {
00346 for (std::size_t j=0; j < numDims; ++j)
00347 {
00348 stress(cell,qp,i,j) = s(i,j) / J(cell,qp);
00349 }
00350 stress(cell,qp,i,i) += p;
00351 }
00352
00353
00354 if(print) std::cout << "stress tensor at cell " << cell
00355 << ", quadrature point " << qp << ":" << std::endl;
00356 if(print) std::cout << " " << stress(cell, qp, 0, 0);
00357 if(print) std::cout << " " << stress(cell, qp, 0, 1);
00358 if(print) std::cout << " " << stress(cell, qp, 0, 2) << std::endl;
00359 if(print) std::cout << " " << stress(cell, qp, 1, 0);
00360 if(print) std::cout << " " << stress(cell, qp, 1, 1);
00361 if(print) std::cout << " " << stress(cell, qp, 1, 2) << std::endl;
00362 if(print) std::cout << " " << stress(cell, qp, 2, 0);
00363 if(print) std::cout << " " << stress(cell, qp, 2, 1);
00364 if(print) std::cout << " " << stress(cell, qp, 2, 2) << std::endl;
00365
00366 if(print) std::cout << "Fp tensor at cell " << cell
00367 << ", quadrature point " << qp << ":" << std::endl;
00368 if(print) std::cout << " " << Fp(cell, qp, 0, 0);
00369 if(print) std::cout << " " << Fp(cell, qp, 0, 1);
00370 if(print) std::cout << " " << Fp(cell, qp, 0, 2) << std::endl;
00371 if(print) std::cout << " " << Fp(cell, qp, 1, 0);
00372 if(print) std::cout << " " << Fp(cell, qp, 1, 1);
00373 if(print) std::cout << " " << Fp(cell, qp, 1, 2) << std::endl;
00374 if(print) std::cout << " " << Fp(cell, qp, 2, 0);
00375 if(print) std::cout << " " << Fp(cell, qp, 2, 1);
00376 if(print) std::cout << " " << Fp(cell, qp, 2, 2) << std::endl;
00377 }
00378 }
00379
00380
00381
00382
00383
00384 for (std::size_t cell=workset.numCells; cell < worksetSize; ++cell)
00385 for (std::size_t qp=0; qp < numQPs; ++qp)
00386 for (std::size_t i=0; i < numDims; ++i)
00387 Fp(cell,qp,i,i) = 1.0;
00388
00389
00390
00391
00392 }
00393
00394 template<typename EvalT, typename Traits>
00395 void
00396 J2Stress<EvalT, Traits>::exponential_map(Intrepid::FieldContainer<ScalarT> & expA,
00397 const Intrepid::FieldContainer<ScalarT> A)
00398 {
00399 tmp.initialize(0.0);
00400 expA.initialize(0.0);
00401
00402 bool converged = false;
00403 ScalarT norm0 = norm(A);
00404
00405 for (std::size_t i=0; i < numDims; ++i)
00406 {
00407 tmp(i,i) = 1.0;
00408 }
00409
00410 ScalarT k = 0.0;
00411 while (!converged)
00412 {
00413
00414 for (std::size_t i=0; i < numDims; ++i)
00415 for (std::size_t j=0; j < numDims; ++j)
00416 expA(i,j) += tmp(i,j);
00417
00418 tmp2.initialize(0.0);
00419 for (std::size_t i=0; i < numDims; ++i)
00420 for (std::size_t j=0; j < numDims; ++j)
00421 for (std::size_t p=0; p < numDims; ++p)
00422 tmp2(i,j) += A(i,p) * tmp(p,j);
00423
00424
00425 k = k + 1.0;
00426 for (std::size_t i=0; i < numDims; ++i)
00427 for (std::size_t j=0; j < numDims; ++j)
00428 tmp(i,j) = (1/k) * tmp2(i,j);
00429
00430 if (norm(tmp)/norm0 < 1.E-14 ) converged = true;
00431
00432 TEUCHOS_TEST_FOR_EXCEPTION( k > 50.0, std::runtime_error,
00433 std::endl << "Error in exponential map, k = " << k <<
00434 "\nnorm0 = " << norm0 <<
00435 "\nnorm = " << norm(tmp)/norm0 <<
00436 "\nA = \n" << A << std::endl);
00437
00438 }
00439 }
00440
00441 template<typename EvalT, typename Traits>
00442 typename EvalT::ScalarT
00443 J2Stress<EvalT, Traits>::norm(Intrepid::FieldContainer<ScalarT> A)
00444 {
00445 ScalarT max(0.0), colsum;
00446
00447 for (std::size_t i(0); i < numDims; ++i)
00448 {
00449 colsum = 0.0;
00450 for (std::size_t j(0); j < numDims; ++j)
00451 colsum += std::abs(A(i,j));
00452 max = (colsum > max) ? colsum : max;
00453 }
00454
00455 return max;
00456 }
00457
00458 }
00459