00001
00002
00003
00004
00005
00006
00007 #include "Teuchos_TestForException.hpp"
00008 #include "Phalanx_DataLayout.hpp"
00009
00010 #include "Intrepid_FunctionSpaceTools.hpp"
00011
00012 namespace LCM {
00013
00014
00015 template<typename EvalT, typename Traits>
00016 MultiScaleStressBase<EvalT, Traits>::
00017 MultiScaleStressBase(const Teuchos::ParameterList& p) :
00018 strain(p.get<std::string> ("Strain Name"),
00019 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Tensor Data Layout")),
00020 elasticModulus(p.get<std::string> ("Elastic Modulus Name"),
00021 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Scalar Data Layout")),
00022 poissonsRatio(p.get<std::string> ("Poissons Ratio Name"),
00023 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Scalar Data Layout")),
00024 stressFieldRealType(std::string("stress_RealType"),
00025 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Tensor Data Layout")),
00026 stress(p.get<std::string> ("Stress Name"),
00027 p.get<Teuchos::RCP<PHX::DataLayout> >("QP Tensor Data Layout")) {
00028
00029
00030 Teuchos::RCP<PHX::DataLayout> tensor_dl =
00031 p.get< Teuchos::RCP<PHX::DataLayout> >("QP Tensor Data Layout");
00032 std::vector<PHX::DataLayout::size_type> dims;
00033 tensor_dl->dimensions(dims);
00034 numQPs = dims[1];
00035 numDims = dims[2];
00036
00037 this->addDependentField(strain);
00038 this->addDependentField(elasticModulus);
00039
00040 Teuchos::ArrayRCP<RealType> s_mem(tensor_dl->size());
00041 stressFieldRealType.setFieldData(s_mem);
00042
00043 numMesoPEs = p.get<int>("Num Meso PEs");
00044 interCommunicator = p.get< Teuchos::RCP<MPI_Comm> >("MPALE Intercommunicator");
00045
00046 loc_data.resize(numMesoPEs);
00047 exchanged_stresses.resize(numDims * numDims);
00048
00049
00050 if(numDims > 1) this->addDependentField(poissonsRatio);
00051
00052 this->addEvaluatedField(stress);
00053
00054 this->setName("MultiScaleStress" + PHX::TypeString<EvalT>::value);
00055
00056 }
00057
00058
00059 template<typename EvalT, typename Traits>
00060 void MultiScaleStressBase<EvalT, Traits>::
00061 postRegistrationSetup(typename Traits::SetupData d,
00062 PHX::FieldManager<Traits>& fm) {
00063 this->utils.setFieldData(stress, fm);
00064 this->utils.setFieldData(strain, fm);
00065 this->utils.setFieldData(elasticModulus, fm);
00066
00067 if(numDims > 1) this->utils.setFieldData(poissonsRatio, fm);
00068 }
00069
00070
00071 template<typename EvalT, typename Traits>
00072 void MultiScaleStressBase<EvalT, Traits>::
00073 evaluateFields(typename Traits::EvalData workset) {
00074 TEUCHOS_TEST_FOR_EXCEPTION("MultiScaleStressBase::evaluateFields not implemented for this template type",
00075 Teuchos::Exceptions::InvalidParameter, "Need specialization.");
00076 }
00077
00078 template<typename EvalT, typename Traits>
00079 void MultiScaleStressBase<EvalT, Traits>::
00080 calcStress(typename Traits::EvalData workset) {
00081
00082 ScalarT lambda, mu;
00083
00084
00085
00086 switch(numDims) {
00087 case 1:
00088 Intrepid::FunctionSpaceTools::tensorMultiplyDataData<ScalarT>(stress, elasticModulus, strain);
00089 break;
00090
00091 case 2:
00092
00093
00094
00095 for(std::size_t cell = 0; cell < workset.numCells; ++cell) {
00096 for(std::size_t qp = 0; qp < numQPs; ++qp) {
00097
00098 lambda = (elasticModulus(cell, qp) * poissonsRatio(cell, qp))
00099 / ((1 + poissonsRatio(cell, qp)) * (1 - 2 * poissonsRatio(cell, qp)));
00100 mu = elasticModulus(cell, qp) / (2 * (1 + poissonsRatio(cell, qp)));
00101 stress(cell, qp, 0, 0) = 2.0 * mu * (strain(cell, qp, 0, 0))
00102 + lambda * (strain(cell, qp, 0, 0) + strain(cell, qp, 1, 1));
00103 stress(cell, qp, 1, 1) = 2.0 * mu * (strain(cell, qp, 1, 1))
00104 + lambda * (strain(cell, qp, 0, 0) + strain(cell, qp, 1, 1));
00105 stress(cell, qp, 0, 1) = 2.0 * mu * (strain(cell, qp, 0, 1));
00106 stress(cell, qp, 1, 0) = stress(cell, qp, 0, 1);
00107
00108 }
00109 }
00110
00111 break;
00112
00113 case 3:
00114
00115
00116
00117 for(std::size_t cell = 0; cell < workset.numCells; ++cell) {
00118 for(std::size_t qp = 0; qp < numQPs; ++qp) {
00119
00120 lambda = (elasticModulus(cell, qp) * poissonsRatio(cell, qp))
00121 / ((1 + poissonsRatio(cell, qp)) * (1 - 2 * poissonsRatio(cell, qp)));
00122 mu = elasticModulus(cell, qp) / (2 * (1 + poissonsRatio(cell, qp)));
00123 stress(cell, qp, 0, 0) = 2.0 * mu * (strain(cell, qp, 0, 0))
00124 + lambda * (strain(cell, qp, 0, 0) + strain(cell, qp, 1, 1) + strain(cell, qp, 2, 2));
00125 stress(cell, qp, 1, 1) = 2.0 * mu * (strain(cell, qp, 1, 1))
00126 + lambda * (strain(cell, qp, 0, 0) + strain(cell, qp, 1, 1) + strain(cell, qp, 2, 2));
00127 stress(cell, qp, 2, 2) = 2.0 * mu * (strain(cell, qp, 2, 2))
00128 + lambda * (strain(cell, qp, 0, 0) + strain(cell, qp, 1, 1) + strain(cell, qp, 2, 2));
00129 stress(cell, qp, 0, 1) = 2.0 * mu * (strain(cell, qp, 0, 1));
00130 stress(cell, qp, 1, 2) = 2.0 * mu * (strain(cell, qp, 1, 2));
00131 stress(cell, qp, 2, 0) = 2.0 * mu * (strain(cell, qp, 2, 0));
00132 stress(cell, qp, 1, 0) = stress(cell, qp, 0, 1);
00133 stress(cell, qp, 2, 1) = stress(cell, qp, 1, 2);
00134 stress(cell, qp, 0, 2) = stress(cell, qp, 2, 0);
00135
00136 }
00137 }
00138
00139 break;
00140 }
00141
00142 return;
00143
00144 }
00145
00146 template<typename EvalT, typename Traits>
00147 void MultiScaleStressBase<EvalT, Traits>::
00148 mesoBridgeStressRealType(PHX::MDField<RealType, Cell, QuadPoint, Dim, Dim>& stressFieldOut,
00149 PHX::MDField<RealType, Cell, QuadPoint, Dim, Dim>& stressFieldIn,
00150 typename Traits::EvalData workset) {
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 int procID = 0;
00161
00162 for(std::size_t cell = 0; cell < workset.numCells; ++cell)
00163 for(std::size_t qp = 0; qp < numQPs; ++qp) {
00164
00165
00166
00167 sendCellQPData(cell, qp, procID, STRESS_TENSOR, stressFieldIn);
00168
00169 procID++;
00170
00171
00172
00173
00174
00175 if(procID >= numMesoPEs || (cell == workset.numCells - 1 && qp == numQPs - 1)) {
00176
00177 rcvCellQPData(procID, STRESS_TENSOR, stressFieldOut);
00178
00179 procID = 0;
00180
00181 }
00182
00183 }
00184
00185 return;
00186
00187 }
00188
00189 template<typename Traits>
00190 void MultiScaleStress<PHAL::AlbanyTraits::Residual, Traits>::
00191 evaluateFields(typename Traits::EvalData workset) {
00192
00193 this->calcStress(workset);
00194
00195 this->mesoBridgeStressRealType(this->stress, this->stress, workset);
00196
00197 return;
00198
00199 }
00200
00201 template<typename Traits>
00202 void MultiScaleStress<PHAL::AlbanyTraits::Jacobian, Traits>::
00203 evaluateFields(typename Traits::EvalData workset) {
00204
00205 this->calcStress(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
00214 this->stressFieldRealType(cell, qp, i, j) = this->stress(cell, qp, i, j).val();
00215
00216 this->mesoBridgeStressRealType(this->stressFieldRealType, this->stressFieldRealType, workset);
00217
00218 for(int cell = 0; cell < (int)workset.numCells; ++cell)
00219 for(int qp = 0; qp < (int)this->numQPs; ++qp)
00220 for(int i = 0; i < (int)this->numDims; ++i)
00221 for(int j = 0; j < (int)this->numDims; ++j)
00222
00223 this->stress(cell, qp, i, j).val() = this->stressFieldRealType(cell, qp, i, j);
00224
00225
00226 double pert = 1.0e-6;
00227 int numIVs = this->stress(0, 0, 0, 0).size();
00228
00229 for(int iv = 0; iv < numIVs; ++iv) {
00230 for(int cell = 0; cell < (int)workset.numCells; ++cell)
00231 for(int qp = 0; qp < (int)this->numQPs; ++qp)
00232 for(int i = 0; i < (int)this->numDims; ++i)
00233 for(int j = 0; j < (int)this->numDims; ++j)
00234
00235 this->stressFieldRealType(cell, qp, i, j) =
00236 this->stress(cell, qp, i, j).val() + pert * this->stress(cell, qp, i, j).fastAccessDx(iv);
00237
00238 this->mesoBridgeStressRealType(this->stressFieldRealType, this->stressFieldRealType, workset);
00239
00240 for(int cell = 0; cell < (int)workset.numCells; ++cell)
00241 for(int qp = 0; qp < (int)this->numQPs; ++qp)
00242 for(int i = 0; i < (int)this->numDims; ++i)
00243 for(int j = 0; j < (int)this->numDims; ++j)
00244
00245 this->stress(cell, qp, i, j).fastAccessDx(iv) =
00246 (this->stressFieldRealType(cell, qp, i, j) - this->stress(cell, qp, i, j).val()) / pert;
00247 }
00248
00249
00250
00251 return;
00252
00253 }
00254
00255
00256 template<typename Traits>
00257 void MultiScaleStress<PHAL::AlbanyTraits::Tangent, Traits>::
00258 evaluateFields(typename Traits::EvalData workset) {
00259
00260 this->calcStress(workset);
00261
00262
00263
00264 for(int cell = 0; cell < (int)workset.numCells; ++cell)
00265 for(int qp = 0; qp < (int)this->numQPs; ++qp)
00266 for(int i = 0; i < (int)this->numDims; ++i)
00267 for(int j = 0; j < (int)this->numDims; ++j)
00268
00269 this->stressFieldRealType(cell, qp, i, j) = this->stress(cell, qp, i, j).val();
00270
00271 this->mesoBridgeStressRealType(this->stressFieldRealType, this->stressFieldRealType, workset);
00272
00273 for(int cell = 0; cell < (int)workset.numCells; ++cell)
00274 for(int qp = 0; qp < (int)this->numQPs; ++qp)
00275 for(int i = 0; i < (int)this->numDims; ++i)
00276 for(int j = 0; j < (int)this->numDims; ++j)
00277
00278 this->stress(cell, qp, i, j).val() = this->stressFieldRealType(cell, qp, i, j);
00279
00280
00281 double pert = 1.0e-6;
00282 int numIVs = this->stress(0, 0, 0, 0).size();
00283
00284 for(int iv = 0; iv < numIVs; ++iv) {
00285 for(int cell = 0; cell < (int)workset.numCells; ++cell)
00286 for(int qp = 0; qp < (int)this->numQPs; ++qp)
00287 for(int i = 0; i < (int)this->numDims; ++i)
00288 for(int j = 0; j < (int)this->numDims; ++j)
00289
00290 this->stressFieldRealType(cell, qp, i, j) =
00291 this->stress(cell, qp, i, j).val() + pert * this->stress(cell, qp, i, j).fastAccessDx(iv);
00292
00293 this->mesoBridgeStressRealType(this->stressFieldRealType, this->stressFieldRealType, workset);
00294
00295 for(int cell = 0; cell < (int)workset.numCells; ++cell)
00296 for(int qp = 0; qp < (int)this->numQPs; ++qp)
00297 for(int i = 0; i < (int)this->numDims; ++i)
00298 for(int j = 0; j < (int)this->numDims; ++j)
00299
00300 this->stress(cell, qp, i, j).fastAccessDx(iv) =
00301 (this->stressFieldRealType(cell, qp, i, j) - this->stress(cell, qp, i, j).val()) / pert;
00302 }
00303
00304
00305
00306 return;
00307
00308 }
00309
00310
00311
00312
00313
00314 template<typename EvalT, typename Traits>
00315 void MultiScaleStressBase<EvalT, Traits>::
00316 sendCellQPData(int cell, int qp, int toProc, MessageType type,
00317 PHX::MDField<RealType, Cell, QuadPoint, Dim, Dim>& stressFieldIn) {
00318
00319
00320 for(std::size_t i = 0; i < numDims; i++)
00321 for(std::size_t dim = 0; dim < numDims; dim++)
00322
00323
00324
00325 exchanged_stresses[numDims * i + dim] = stressFieldIn(cell, qp, i, dim);
00326
00327
00328
00329
00330 MPI_Send(&exchanged_stresses[0],
00331 exchanged_stresses.size(),
00332 MPI_DOUBLE,
00333 toProc,
00334 type,
00335 *interCommunicator.get());
00336
00337
00338
00339 loc_data[toProc].cell = cell;
00340 loc_data[toProc].qp = qp;
00341
00342 return;
00343
00344 }
00345
00346 template<typename EvalT, typename Traits>
00347 void MultiScaleStressBase<EvalT, Traits>::
00348 rcvCellQPData(int procIDReached, MessageType type,
00349 PHX::MDField<RealType, Cell, QuadPoint, Dim, Dim>& stressFieldOut) {
00350
00351 MPI_Status status;
00352
00353
00354
00355 for(int proc_ctr = 0; proc_ctr < procIDReached; proc_ctr++) {
00356
00357
00358
00359
00360
00361
00362 MPI_Recv(&exchanged_stresses[0],
00363 exchanged_stresses.size(),
00364 MPI_DOUBLE,
00365 MPI_ANY_SOURCE,
00366 type,
00367 *interCommunicator.get(),
00368 &status);
00369
00370 int proc = status.MPI_SOURCE;
00371
00372
00373 for(std::size_t i = 0; i < numDims; i++)
00374 for(std::size_t dim = 0; dim < numDims; dim++)
00375
00376
00377
00378 stressFieldOut(loc_data[proc].cell, loc_data[proc].qp, i, dim) = exchanged_stresses[numDims * i + dim];
00379
00380 }
00381
00382 return;
00383
00384 }
00385
00386
00387 }
00388