00001
00002
00003
00004
00005
00006
00007 #include <Intrepid_MiniTensor.h>
00008 #include "Teuchos_TestForException.hpp"
00009 #include "Phalanx_DataLayout.hpp"
00010 #include "Intrepid_FunctionSpaceTools.hpp"
00011 #include "QCAD_MaterialDatabase.hpp"
00012
00013 namespace LCM {
00014
00015 template<typename EvalT, typename Traits>
00016 LameStressBase<EvalT, Traits>::
00017 LameStressBase(Teuchos::ParameterList& p) :
00018 defGradField(p.get<std::string>("DefGrad Name"),
00019 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Tensor Data Layout")),
00020 stressField(p.get<std::string>("Stress Name"),
00021 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Tensor Data Layout") ),
00022 lameMaterialModel(Teuchos::RCP<LameMaterial>())
00023 {
00024
00025 tensor_dl = p.get< Teuchos::RCP<PHX::DataLayout> >("QP Tensor Data Layout");
00026 std::vector<PHX::DataLayout::size_type> dims;
00027 tensor_dl->dimensions(dims);
00028 numQPs = dims[1];
00029 numDims = dims[2];
00030
00031 TEUCHOS_TEST_FOR_EXCEPTION(this->numDims != 3, Teuchos::Exceptions::InvalidParameter, " LAME materials enabled only for three-dimensional analyses.");
00032
00033 defGradName = p.get<std::string>("DefGrad Name")+"_old";
00034 this->addDependentField(defGradField);
00035
00036 stressName = p.get<std::string>("Stress Name")+"_old";
00037 this->addEvaluatedField(stressField);
00038
00039 this->setName("LameStress"+PHX::TypeString<EvalT>::value);
00040
00041
00042 lameMaterialModelName = p.get<std::string>("Lame Material Model", "Elastic");
00043 Teuchos::ParameterList& lameMaterialParameters = p.sublist("Lame Material Parameters");
00044
00045
00046 int haveMatDB = p.get<bool>("Have MatDB", false);
00047
00048 std::string ebName = p.get<std::string>("Element Block Name", "Missing");
00049
00050
00051 if (haveMatDB) {
00052
00053 bool dataFromDatabase = lameMaterialParameters.get<bool>("Material Dependent Data Source",false);
00054
00055
00056 if (dataFromDatabase) {
00057 Teuchos::RCP<QCAD::MaterialDatabase> materialDB = p.get< Teuchos::RCP<QCAD::MaterialDatabase> >("MaterialDB");
00058
00059 lameMaterialModelName = materialDB->getElementBlockParam<std::string>(ebName, "Lame Material Model");
00060 lameMaterialParameters = materialDB->getElementBlockSublist(ebName, "Lame Material Parameters");
00061 }
00062 }
00063
00064
00065
00066
00067
00068 lameMaterialModel = LameUtils::constructLameMaterialModel(lameMaterialModelName, lameMaterialParameters);
00069
00070
00071 lameMaterialModelStateVariableNames = LameUtils::getStateVariableNames(lameMaterialModelName, lameMaterialParameters);
00072
00073
00074 Teuchos::RCP<PHX::DataLayout> dataLayout = p.get<Teuchos::RCP<PHX::DataLayout> >("QP Scalar Data Layout");
00075 for(unsigned int i=0 ; i<lameMaterialModelStateVariableNames.size() ; ++i){
00076 PHX::MDField<ScalarT,Cell,QuadPoint,Dim,Dim> lameMaterialModelStateVariableField(lameMaterialModelStateVariableNames[i], dataLayout);
00077 this->addEvaluatedField(lameMaterialModelStateVariableField);
00078 lameMaterialModelStateVariableFields.push_back(lameMaterialModelStateVariableField);
00079 }
00080 }
00081
00082 template<typename EvalT, typename Traits>
00083 void LameStressBase<EvalT, Traits>::
00084 postRegistrationSetup(typename Traits::SetupData d,
00085 PHX::FieldManager<Traits>& fm)
00086 {
00087 this->utils.setFieldData(defGradField,fm);
00088 this->utils.setFieldData(stressField,fm);
00089 for(unsigned int i=0 ; i<lameMaterialModelStateVariableFields.size() ; ++i)
00090 this->utils.setFieldData(lameMaterialModelStateVariableFields[i],fm);
00091 }
00092
00093 template<typename EvalT, typename Traits>
00094 void LameStressBase<EvalT, Traits>::
00095 evaluateFields(typename Traits::EvalData workset)
00096 {
00097 TEUCHOS_TEST_FOR_EXCEPTION("LameStressBase::evaluateFields not implemented for this template type",
00098 Teuchos::Exceptions::InvalidParameter, "Need specialization.");
00099 }
00100
00101
00102
00103 template<typename Traits>
00104 void LameStress<PHAL::AlbanyTraits::Residual, Traits>::
00105 evaluateFields(typename Traits::EvalData workset)
00106 {
00107
00108 Teuchos::RCP<LameMatParams> matp = Teuchos::rcp(new LameMatParams());
00109 this->setMatP(matp, workset);
00110
00111 this->calcStressRealType(this->stressField, this->defGradField, workset, matp);
00112
00113 this->freeMatP(matp);
00114
00115 }
00116
00117 template<typename Traits>
00118 void LameStress<PHAL::AlbanyTraits::Jacobian, Traits>::
00119 evaluateFields(typename Traits::EvalData workset)
00120 {
00121
00122 PHAL::AlbanyTraits::Jacobian::ScalarT scalarToForceAllocation=this->defGradField(0,0,0,0);
00123 for (int cell=0; cell < (int)workset.numCells; ++cell)
00124 for (int qp=0; qp < (int)this->numQPs; ++qp)
00125 for (int i=0; i < (int)this->numDims; ++i)
00126 for (int j=0; j < (int)this->numDims; ++j)
00127 this->stressField(cell,qp,i,j) = scalarToForceAllocation;
00128
00129
00130 PHX::MDField<RealType,Cell,QuadPoint,Dim,Dim> stressFieldRealType("stress_RealType", this->tensor_dl);
00131 PHX::MDField<RealType,Cell,QuadPoint,Dim,Dim> defGradFieldRealType("defGrad_RealType", this->tensor_dl);
00132 Teuchos::ArrayRCP<RealType> s_mem(this->tensor_dl->size());
00133 Teuchos::ArrayRCP<RealType> d_mem(this->tensor_dl->size());
00134 stressFieldRealType.setFieldData(s_mem);
00135 defGradFieldRealType.setFieldData(d_mem);
00136
00137
00138 Teuchos::RCP<LameMatParams> matp = Teuchos::rcp(new LameMatParams());
00139 this->setMatP(matp, workset);
00140
00141
00142
00143 for (int cell=0; cell < (int)workset.numCells; ++cell)
00144 for (int qp=0; qp < (int)this->numQPs; ++qp)
00145 for (int i=0; i < (int)this->numDims; ++i)
00146 for (int j=0; j < (int)this->numDims; ++j)
00147 defGradFieldRealType(cell,qp,i,j) = this->defGradField(cell,qp,i,j).val();
00148
00149 this->calcStressRealType(stressFieldRealType, defGradFieldRealType, workset, matp);
00150
00151 for (int cell=0; cell < (int)workset.numCells; ++cell)
00152 for (int qp=0; qp < (int)this->numQPs; ++qp)
00153 for (int i=0; i < (int)this->numDims; ++i)
00154 for (int j=0; j < (int)this->numDims; ++j)
00155 this->stressField(cell,qp,i,j).val() = stressFieldRealType(cell,qp,i,j);
00156
00157
00158 double pert=1.0e-6;
00159 int numIVs = this->defGradField(0,0,0,0).size();
00160 for (int iv=0; iv < numIVs; ++iv) {
00161 for (int cell=0; cell < (int)workset.numCells; ++cell)
00162 for (int qp=0; qp < (int)this->numQPs; ++qp)
00163 for (int i=0; i < (int)this->numDims; ++i)
00164 for (int j=0; j < (int)this->numDims; ++j)
00165 defGradFieldRealType(cell,qp,i,j) =
00166 this->defGradField(cell,qp,i,j).val() + pert*this->defGradField(cell,qp,i,j).fastAccessDx(iv);
00167
00168 this->calcStressRealType(stressFieldRealType, defGradFieldRealType, workset, matp);
00169
00170 for (int cell=0; cell < (int)workset.numCells; ++cell)
00171 for (int qp=0; qp < (int)this->numQPs; ++qp)
00172 for (int i=0; i < (int)this->numDims; ++i)
00173 for (int j=0; j < (int)this->numDims; ++j)
00174 this->stressField(cell,qp,i,j).fastAccessDx(iv) =
00175 (stressFieldRealType(cell,qp,i,j) - this->stressField(cell,qp,i,j).val()) / pert;
00176 }
00177
00178
00179 this->freeMatP(matp);
00180 }
00181
00182
00183 template<typename Traits>
00184 void LameStress<PHAL::AlbanyTraits::Tangent, Traits>::
00185 evaluateFields(typename Traits::EvalData workset)
00186 {
00187
00188 PHAL::AlbanyTraits::Tangent::ScalarT scalarToForceAllocation=this->defGradField(0,0,0,0);
00189 for (int cell=0; cell < (int)workset.numCells; ++cell)
00190 for (int qp=0; qp < (int)this->numQPs; ++qp)
00191 for (int i=0; i < (int)this->numDims; ++i)
00192 for (int j=0; j < (int)this->numDims; ++j)
00193 this->stressField(cell,qp,i,j) = scalarToForceAllocation;
00194
00195
00196 PHX::MDField<RealType,Cell,QuadPoint,Dim,Dim> stressFieldRealType("stress_RealType", this->tensor_dl);
00197 PHX::MDField<RealType,Cell,QuadPoint,Dim,Dim> defGradFieldRealType("defGrad_RealType", this->tensor_dl);
00198 Teuchos::ArrayRCP<RealType> s_mem(this->tensor_dl->size());
00199 Teuchos::ArrayRCP<RealType> d_mem(this->tensor_dl->size());
00200 stressFieldRealType.setFieldData(s_mem);
00201 defGradFieldRealType.setFieldData(d_mem);
00202
00203
00204 Teuchos::RCP<LameMatParams> matp = Teuchos::rcp(new LameMatParams());
00205 this->setMatP(matp, workset);
00206
00207
00208
00209 for (int cell=0; cell < (int)workset.numCells; ++cell)
00210 for (int qp=0; qp < (int)this->numQPs; ++qp)
00211 for (int i=0; i < (int)this->numDims; ++i)
00212 for (int j=0; j < (int)this->numDims; ++j)
00213 defGradFieldRealType(cell,qp,i,j) = this->defGradField(cell,qp,i,j).val();
00214
00215 this->calcStressRealType(stressFieldRealType, defGradFieldRealType, workset, matp);
00216
00217 for (int cell=0; cell < (int)workset.numCells; ++cell)
00218 for (int qp=0; qp < (int)this->numQPs; ++qp)
00219 for (int i=0; i < (int)this->numDims; ++i)
00220 for (int j=0; j < (int)this->numDims; ++j)
00221 this->stressField(cell,qp,i,j).val() = stressFieldRealType(cell,qp,i,j);
00222
00223
00224 double pert=1.0e-8;
00225 int numIVs = this->defGradField(0,0,0,0).size();
00226 for (int iv=0; iv < numIVs; ++iv) {
00227 for (int cell=0; cell < (int)workset.numCells; ++cell)
00228 for (int qp=0; qp < (int)this->numQPs; ++qp)
00229 for (int i=0; i < (int)this->numDims; ++i)
00230 for (int j=0; j < (int)this->numDims; ++j)
00231 defGradFieldRealType(cell,qp,i,j) =
00232 this->defGradField(cell,qp,i,j).val() + pert*this->defGradField(cell,qp,i,j).fastAccessDx(iv);
00233
00234 this->calcStressRealType(stressFieldRealType, defGradFieldRealType, workset, matp);
00235
00236 for (int cell=0; cell < (int)workset.numCells; ++cell)
00237 for (int qp=0; qp < (int)this->numQPs; ++qp)
00238 for (int i=0; i < (int)this->numDims; ++i)
00239 for (int j=0; j < (int)this->numDims; ++j)
00240 this->stressField(cell,qp,i,j).fastAccessDx(iv) =
00241 (stressFieldRealType(cell,qp,i,j) - this->stressField(cell,qp,i,j).val()) / pert;
00242 }
00243
00244
00245 this->freeMatP(matp);
00246 }
00247
00248 template<typename EvalT, typename Traits>
00249 void LameStressBase<EvalT, Traits>::
00250 setMatP(Teuchos::RCP<LameMatParams>& matp,
00251 typename Traits::EvalData workset)
00252 {
00253
00254 RealType deltaT = 1.0;
00255
00256 int numStateVariables = (int)(this->lameMaterialModelStateVariableNames.size());
00257
00258
00259
00260 int numMaterialEvaluations = workset.numCells * this->numQPs;
00261
00262 double* strainRate = new double[6*numMaterialEvaluations];
00263 double* spin = new double[3*numMaterialEvaluations];
00264 double* leftStretch = new double[6*numMaterialEvaluations];
00265 double* rotation = new double[9*numMaterialEvaluations];
00266 double* stressOld = new double[6*numMaterialEvaluations];
00267 double* stressNew = new double[6*numMaterialEvaluations];
00268 double* stateOld = new double[numStateVariables*numMaterialEvaluations];
00269 double* stateNew = new double[numStateVariables*numMaterialEvaluations];
00270
00271
00272
00273
00274 matp->nelements = numMaterialEvaluations;
00275 matp->dt = deltaT;
00276 matp->time = 0.0;
00277 matp->strain_rate = strainRate;
00278 matp->spin = spin;
00279 matp->left_stretch = leftStretch;
00280 matp->rotation = rotation;
00281 matp->state_old = stateOld;
00282 matp->state_new = stateNew;
00283 matp->stress_old = stressOld;
00284 matp->stress_new = stressNew;
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 }
00296
00297 template<typename EvalT, typename Traits>
00298 void LameStressBase<EvalT, Traits>::
00299 freeMatP(Teuchos::RCP<LameMatParams>& matp)
00300 {
00301 delete [] matp->strain_rate;
00302 delete [] matp->spin;
00303 delete [] matp->left_stretch;
00304 delete [] matp->rotation;
00305 delete [] matp->state_old;
00306 delete [] matp->state_new;
00307 delete [] matp->stress_old;
00308 delete [] matp->stress_new;
00309 }
00310
00311 template<typename EvalT, typename Traits>
00312 void LameStressBase<EvalT, Traits>::
00313 calcStressRealType(PHX::MDField<RealType,Cell,QuadPoint,Dim,Dim>& stressFieldRef,
00314 PHX::MDField<RealType,Cell,QuadPoint,Dim,Dim>& defGradFieldRef,
00315 typename Traits::EvalData workset,
00316 Teuchos::RCP<LameMatParams>& matp)
00317 {
00318
00319 Albany::MDArray oldDefGrad = (*workset.stateArrayPtr)[defGradName];
00320 Albany::MDArray oldStress = (*workset.stateArrayPtr)[stressName];
00321
00322 int numStateVariables = (int)(this->lameMaterialModelStateVariableNames.size());
00323
00324
00325 double* strainRatePtr = matp->strain_rate;
00326 double* spinPtr = matp->spin;
00327 double* leftStretchPtr = matp->left_stretch;
00328 double* rotationPtr = matp->rotation;
00329 double* stateOldPtr = matp->state_old;
00330 double* stressOldPtr = matp->stress_old;
00331
00332 double deltaT = matp->dt;
00333
00334 for (int cell=0; cell < (int)workset.numCells; ++cell) {
00335 for (int qp=0; qp < (int)numQPs; ++qp) {
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 Intrepid::Tensor<RealType> Fnew(
00376 defGradFieldRef(cell,qp,0,0), defGradFieldRef(cell,qp,0,1), defGradFieldRef(cell,qp,0,2),
00377 defGradFieldRef(cell,qp,1,0), defGradFieldRef(cell,qp,1,1), defGradFieldRef(cell,qp,1,2),
00378 defGradFieldRef(cell,qp,2,0), defGradFieldRef(cell,qp,2,1), defGradFieldRef(cell,qp,2,2) );
00379
00380
00381 Intrepid::Tensor<RealType> Fold( oldDefGrad(cell,qp,0,0), oldDefGrad(cell,qp,0,1), oldDefGrad(cell,qp,0,2),
00382 oldDefGrad(cell,qp,1,0), oldDefGrad(cell,qp,1,1), oldDefGrad(cell,qp,1,2),
00383 oldDefGrad(cell,qp,2,0), oldDefGrad(cell,qp,2,1), oldDefGrad(cell,qp,2,2) );
00384
00385
00386 Intrepid::Tensor<RealType> Finc = Fnew * Intrepid::inverse(Fold);
00387
00388
00389 Intrepid::Tensor<RealType> V(3), R(3);
00390 boost::tie(V,R) = Intrepid::polar_left_eig(Fnew);
00391
00392
00393 Intrepid::Tensor<RealType> Vinc(3), Rinc(3), logVinc(3);
00394 boost::tie(Vinc,Rinc,logVinc) = Intrepid::polar_left_logV_lame(Finc);
00395
00396
00397 Intrepid::Tensor<RealType> logRinc = Intrepid::log_rotation(Rinc);
00398
00399
00400 Intrepid::Tensor<RealType> logFinc = Intrepid::bch(logVinc, logRinc);
00401
00402
00403 Intrepid::Tensor<RealType> L = RealType(1.0/deltaT)*logFinc;
00404
00405
00406 Intrepid::Tensor<RealType> D = Intrepid::sym(L);
00407
00408
00409 Intrepid::Tensor<RealType> W = Intrepid::skew(L);
00410
00411
00412
00413 strainRatePtr[0] = ( D(0,0) );
00414 strainRatePtr[1] = ( D(1,1) );
00415 strainRatePtr[2] = ( D(2,2) );
00416 strainRatePtr[3] = ( D(0,1) );
00417 strainRatePtr[4] = ( D(1,2) );
00418 strainRatePtr[5] = ( D(0,2) );
00419
00420 spinPtr[0] = ( W(0,1) );
00421 spinPtr[1] = ( W(1,2) );
00422 spinPtr[2] = ( W(0,2) );
00423
00424 leftStretchPtr[0] = ( V(0,0) );
00425 leftStretchPtr[1] = ( V(1,1) );
00426 leftStretchPtr[2] = ( V(2,2) );
00427 leftStretchPtr[3] = ( V(0,1) );
00428 leftStretchPtr[4] = ( V(1,2) );
00429 leftStretchPtr[5] = ( V(0,2) );
00430
00431 rotationPtr[0] = ( R(0,0) );
00432 rotationPtr[1] = ( R(1,1) );
00433 rotationPtr[2] = ( R(2,2) );
00434 rotationPtr[3] = ( R(0,1) );
00435 rotationPtr[4] = ( R(1,2) );
00436 rotationPtr[5] = ( R(0,2) );
00437 rotationPtr[6] = ( R(1,0) );
00438 rotationPtr[7] = ( R(2,1) );
00439 rotationPtr[8] = ( R(2,0) );
00440
00441 stressOldPtr[0] = oldStress(cell,qp,0,0);
00442 stressOldPtr[1] = oldStress(cell,qp,1,1);
00443 stressOldPtr[2] = oldStress(cell,qp,2,2);
00444 stressOldPtr[3] = oldStress(cell,qp,0,1);
00445 stressOldPtr[4] = oldStress(cell,qp,1,2);
00446 stressOldPtr[5] = oldStress(cell,qp,0,2);
00447
00448
00449 strainRatePtr += 6;
00450 spinPtr += 3;
00451 leftStretchPtr += 6;
00452 rotationPtr += 9;
00453 stressOldPtr += 6;
00454
00455
00456 for(int iVar=0 ; iVar<numStateVariables ; iVar++, stateOldPtr++){
00457
00458
00459 const std::string& variableName = this->lameMaterialModelStateVariableNames[iVar]+"_old";
00460 Albany::MDArray stateVar = (*workset.stateArrayPtr)[variableName];
00461 *stateOldPtr = stateVar(cell,qp);
00462 }
00463 }
00464 }
00465
00466
00467 this->lameMaterialModel->loadStepInit(matp.get());
00468
00469
00470 this->lameMaterialModel->getStress(matp.get());
00471
00472 double* stressNewPtr = matp->stress_new;
00473
00474
00475 for (std::size_t cell=0; cell < workset.numCells; ++cell) {
00476 for (std::size_t qp=0; qp < numQPs; ++qp) {
00477
00478
00479 stressFieldRef(cell,qp,0,0) = stressNewPtr[0];
00480 stressFieldRef(cell,qp,1,1) = stressNewPtr[1];
00481 stressFieldRef(cell,qp,2,2) = stressNewPtr[2];
00482 stressFieldRef(cell,qp,0,1) = stressNewPtr[3];
00483 stressFieldRef(cell,qp,1,2) = stressNewPtr[4];
00484 stressFieldRef(cell,qp,0,2) = stressNewPtr[5];
00485 stressFieldRef(cell,qp,1,0) = stressNewPtr[3];
00486 stressFieldRef(cell,qp,2,1) = stressNewPtr[4];
00487 stressFieldRef(cell,qp,2,0) = stressNewPtr[5];
00488
00489 stressNewPtr += 6;
00490 }
00491 }
00492
00493
00494 double* stateNewPtr = matp->state_new;
00495 for (std::size_t cell=0; cell < workset.numCells; ++cell) {
00496 for (std::size_t qp=0; qp < numQPs; ++qp) {
00497
00498 for(int iVar=0 ; iVar<numStateVariables ; iVar++, stateNewPtr++)
00499 this->lameMaterialModelStateVariableFields[iVar](cell,qp) = *stateNewPtr;
00500 }
00501 }
00502
00503 }
00504
00505
00506 }
00507