• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

MultiScaleStress_Def.hpp

Go to the documentation of this file.
00001 //*****************************************************************//
00002 //    Albany 2.0:  Copyright 2012 Sandia Corporation               //
00003 //    This Software is released under the BSD license detailed     //
00004 //    in the file "license.txt" in the top-level Albany directory  //
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   // Pull out numQPs and numDims from a Layout
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   // PoissonRatio not used in 1D stress calc
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   // Calculate stresses
00085 
00086   switch(numDims) {
00087     case 1:
00088       Intrepid::FunctionSpaceTools::tensorMultiplyDataData<ScalarT>(stress, elasticModulus, strain);
00089       break;
00090 
00091     case 2:
00092 
00093       // Compute Stress (with the plane strain assumption for now)
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       // Compute Stress
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   // Communicate stress to and from MPALE
00153 
00154   /*
00155     Background: Here, we send the stress state for each QP for each cell in the
00156     workset to a waiting MPALE process. But, we limit the number of processes that
00157     can be used to numMesoPEs. So, we will process this in numMesoPEs sized chunks.
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       // send the stress tensor for this cell and qp to a processor (procID)
00166 
00167       sendCellQPData(cell, qp, procID, STRESS_TENSOR, stressFieldIn);
00168 
00169       procID++; // go to the next qp and processor (and possibly cell)
00170 
00171       // Chunk section: If we have sent all the data available (cell == workset.numCells - 1 AND
00172       // qp == numQPs - 1) OR we have sent requests to all the processors available, we receive the
00173       // data back.
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   // Begin Finite Difference
00208   // Do Base unperturbed case
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   // Do Perturbations
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 // Tangent implementation is Identical to Jacobian
00256 template<typename Traits>
00257 void MultiScaleStress<PHAL::AlbanyTraits::Tangent, Traits>::
00258 evaluateFields(typename Traits::EvalData workset) {
00259 
00260   this->calcStress(workset);
00261 
00262   // Begin Finite Difference
00263   // Do Base unperturbed case
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   // Do Perturbations
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   // Fill in array
00320   for(std::size_t i = 0; i < numDims; i++)
00321     for(std::size_t dim = 0; dim < numDims; dim++)
00322 
00323       // Store the stress tensor for this cell and qp
00324 
00325       exchanged_stresses[numDims * i + dim] = stressFieldIn(cell, qp, i, dim);
00326 
00327 
00328   // send it
00329 
00330   MPI_Send(&exchanged_stresses[0],     /* the stress tensor */
00331            exchanged_stresses.size(),         /* its length (9) */
00332            MPI_DOUBLE,                        /* data items are doubles */
00333            toProc,                            /* destination process */
00334            type,                              /* user chosen message tag */
00335            *interCommunicator.get());          /* the MPALE communicator */
00336 
00337   // Save the cell and qp ids for unpacking
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   // Loop over all the processors participating
00354 
00355   for(int proc_ctr = 0; proc_ctr < procIDReached; proc_ctr++) {
00356 
00357     /*
00358      * Receive the stress tensor from the first MPALE process to send one
00359      * No need to receive them in order
00360      */
00361 
00362     MPI_Recv(&exchanged_stresses[0],           /* incoming tensor */
00363              exchanged_stresses.size(),
00364              MPI_DOUBLE,                         /* of type double */
00365              MPI_ANY_SOURCE,                     /* receive from any sender */
00366              type,
00367              *interCommunicator.get(),           /* from one of the MPALE processes */
00368              &status);                          /* info about the received message */
00369 
00370     int proc = status.MPI_SOURCE; // What MPALE process sent the message?
00371 
00372     // Fill in the stress info back into the Albany array
00373     for(std::size_t i = 0; i < numDims; i++)
00374       for(std::size_t dim = 0; dim < numDims; dim++)
00375 
00376         // Store the stress tensor for this cell and qp
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 

Generated on Wed Mar 26 2014 18:36:40 for Albany: a Trilinos-based PDE code by  doxygen 1.7.1