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

SurfaceVectorResidual_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 <Intrepid_MiniTensor.h>
00008 
00009 #include "Teuchos_TestForException.hpp"
00010 #include "Phalanx_DataLayout.hpp"
00011 
00012 namespace LCM {
00013 
00014   //----------------------------------------------------------------------------
00015   template<typename EvalT, typename Traits>
00016   SurfaceVectorResidual<EvalT, Traits>::
00017   SurfaceVectorResidual(Teuchos::ParameterList& p,
00018                         const Teuchos::RCP<Albany::Layouts>& dl) :
00019     thickness      (p.get<double>("thickness")),
00020     cubature       (p.get<Teuchos::RCP<Intrepid::Cubature<RealType> > >("Cubature")),
00021     intrepidBasis  (p.get<Teuchos::RCP<Intrepid::Basis<RealType, Intrepid::FieldContainer<RealType> > > >("Intrepid Basis")),
00022     stress         (p.get<std::string>("Stress Name"),dl->qp_tensor),
00023     currentBasis   (p.get<std::string>("Current Basis Name"),dl->qp_tensor),
00024     refDualBasis   (p.get<std::string>("Reference Dual Basis Name"),dl->qp_tensor),
00025     refNormal      (p.get<std::string>("Reference Normal Name"),dl->qp_vector),
00026     refArea        (p.get<std::string>("Reference Area Name"),dl->qp_scalar),
00027     force          (p.get<std::string>("Surface Vector Residual Name"),dl->node_vector),
00028     use_cohesive_traction_(p.get<bool>("Use Cohesive Traction", false)),
00029     compute_membrane_forces_(p.get<bool>("Compute Membrane Forces", false))
00030   {
00031     this->addDependentField(currentBasis);
00032     this->addDependentField(refDualBasis);
00033     this->addDependentField(refNormal);    
00034     this->addDependentField(refArea);
00035 
00036     this->addEvaluatedField(force);
00037 
00038     this->setName("Surface Vector Residual"+PHX::TypeString<EvalT>::value);
00039 
00040     // if enabled grab the cohesive tractions
00041     if (use_cohesive_traction_) {
00042       PHX::MDField<ScalarT, Cell, QuadPoint, Dim> ct(p.get<std::string>("Cohesive Traction Name"), dl->qp_vector);
00043       traction_ = ct;
00044       this->addDependentField(traction_);
00045     } else {
00046       this->addDependentField(stress);      
00047     }
00048 
00049     std::vector<PHX::DataLayout::size_type> dims;
00050     dl->node_vector->dimensions(dims);
00051     worksetSize = dims[0];
00052     numNodes = dims[1];
00053     numDims = dims[2];
00054 
00055     numQPs = cubature->getNumPoints();
00056 
00057     numPlaneNodes = numNodes / 2;
00058     numPlaneDims = numDims - 1;
00059 
00060     // Allocate Temporary FieldContainers
00061     refValues.resize(numPlaneNodes, numQPs);
00062     refGrads.resize(numPlaneNodes, numQPs, numPlaneDims);
00063     refPoints.resize(numQPs, numPlaneDims);
00064     refWeights.resize(numQPs);
00065 
00066     // Pre-Calculate reference element quantitites
00067     cubature->getCubature(refPoints, refWeights);
00068     intrepidBasis->getValues(refValues, refPoints, Intrepid::OPERATOR_VALUE);
00069     intrepidBasis->getValues(refGrads, refPoints, Intrepid::OPERATOR_GRAD);
00070   }
00071 
00072   //----------------------------------------------------------------------------
00073   template<typename EvalT, typename Traits>
00074   void SurfaceVectorResidual<EvalT, Traits>::
00075   postRegistrationSetup(typename Traits::SetupData d,
00076                         PHX::FieldManager<Traits>& fm)
00077   {
00078     this->utils.setFieldData(currentBasis,fm);
00079     this->utils.setFieldData(refDualBasis,fm);
00080     this->utils.setFieldData(refNormal,fm);
00081     this->utils.setFieldData(refArea,fm);
00082     this->utils.setFieldData(force,fm);
00083 
00084     if (use_cohesive_traction_) {
00085       this->utils.setFieldData(traction_,fm);
00086     } else {
00087       this->utils.setFieldData(stress,fm);
00088     }
00089   }
00090 
00091   //----------------------------------------------------------------------------
00092   template<typename EvalT, typename Traits>
00093   void SurfaceVectorResidual<EvalT, Traits>::
00094   evaluateFields(typename Traits::EvalData workset)
00095   {
00096     // define and initialize tensors/vectors
00097     Intrepid::Vector<ScalarT> f_plus(0, 0, 0), f_minus(0, 0, 0);
00098     ScalarT dgapdxN, tmp1, tmp2, dndxbar, dFdx_plus, dFdx_minus;
00099 
00100     // manually fill the permutation tensor
00101     Intrepid::Tensor3<MeshScalarT> e(3, Intrepid::ZEROS);
00102     e(0, 1, 2) = e(1, 2, 0) = e(2, 0, 1) = 1.0;
00103     e(0, 2, 1) = e(1, 0, 2) = e(2, 1, 0) = -1.0;
00104 
00105     // 2nd-order identity tensor
00106     const Intrepid::Tensor<MeshScalarT> I = Intrepid::identity<MeshScalarT>(3);
00107 
00108     for (std::size_t cell(0); cell < workset.numCells; ++cell) {
00109       for (std::size_t node(0); node < numPlaneNodes; ++node) {
00110 
00111         force(cell, node, 0) = 0.0;
00112         force(cell, node, 1) = 0.0;
00113         force(cell, node, 2) = 0.0;
00114         int topNode = node + numPlaneNodes;
00115         force(cell, topNode, 0) = 0.0;
00116         force(cell, topNode, 1) = 0.0;
00117         force(cell, topNode, 2) = 0.0;
00118 
00119         for (std::size_t pt(0); pt < numQPs; ++pt) {
00120           // deformed bases
00121           Intrepid::Vector<ScalarT> g_0(3, &currentBasis(cell, pt, 0, 0));
00122           Intrepid::Vector<ScalarT> g_1(3, &currentBasis(cell, pt, 1, 0));
00123           Intrepid::Vector<ScalarT> n(3, &currentBasis(cell, pt, 2, 0));
00124           // ref bases
00125           Intrepid::Vector<MeshScalarT> G0(3, &refDualBasis(cell, pt, 0, 0));
00126           Intrepid::Vector<MeshScalarT> G1(3, &refDualBasis(cell, pt, 1, 0));
00127           Intrepid::Vector<MeshScalarT> G2(3, &refDualBasis(cell, pt, 2, 0));
00128           // ref normal
00129           Intrepid::Vector<MeshScalarT> N(3, &refNormal(cell, pt, 0));
00130 
00131           // compute dFdx_plus_or_minus
00132           f_plus.clear();
00133           f_minus.clear();
00134 
00135           // h * P * dFperpdx --> +/- \lambda * P * N
00136           if (use_cohesive_traction_) {
00137             Intrepid::Vector<ScalarT> T(3, &traction_(cell,pt,0));
00138             f_plus  =  refValues(node, pt) * T;
00139             f_minus = -refValues(node, pt) * T;
00140           } else {
00141             Intrepid::Tensor<ScalarT> P(3, &stress(cell, pt, 0, 0));
00142 
00143             f_plus  =   refValues(node, pt) * P * N;
00144             f_minus = - refValues(node, pt) * P * N;
00145 
00146             if (compute_membrane_forces_) {
00147               for (int m(0); m < numDims; ++m) {
00148                 for (int i(0); i < numDims; ++i) {
00149                   for (int L(0); L < numDims; ++L) {
00150 
00151                     // tmp1 = (1/2) * delta * lambda_{,alpha} * G^{alpha L}
00152                     tmp1 = 0.5 * I(m,i) * ( refGrads(node, pt, 0) * G0(L) + 
00153                                             refGrads(node, pt, 1) * G1(L) );
00154 
00155                     // tmp2 = (1/2) * dndxbar * G^{3}
00156                     dndxbar = 0.0;
00157                     for (int r(0); r < numDims; ++r) {
00158                       for (int s(0); s < numDims; ++s) {
00159                         //dndxbar(m, i) += e(i, r, s)
00160                         dndxbar += e(i, r, s) 
00161                           * (g_1(r) * refGrads(node, pt, 0) - 
00162                              g_0(r) * refGrads(node, pt, 1))
00163                           * (I(m, s) - n(m) * n(s)) /
00164                           Intrepid::norm(Intrepid::cross(g_0, g_1));
00165                       }
00166                     }
00167                     tmp2 = 0.5 * dndxbar * G2(L);
00168 
00169                     // dFdx_plus
00170                     dFdx_plus = tmp1 + tmp2;
00171 
00172                     // dFdx_minus
00173                     dFdx_minus = tmp1 + tmp2;
00174 
00175                     //F = h * P:dFdx
00176                     f_plus(i) += thickness * P(m, L) * dFdx_plus;
00177                     f_minus(i) += thickness * P(m, L) * dFdx_minus;
00178 
00179                   }
00180                 }
00181               }
00182             }
00183           }
00184 
00185           // area (Reference) = |Jacobian| * weights
00186           force(cell, topNode, 0) += f_plus(0) * refArea(cell, pt);
00187           force(cell, topNode, 1) += f_plus(1) * refArea(cell, pt);
00188           force(cell, topNode, 2) += f_plus(2) * refArea(cell, pt);
00189 
00190           force(cell, node, 0) += f_minus(0) * refArea(cell, pt);
00191           force(cell, node, 1) += f_minus(1) * refArea(cell, pt);
00192           force(cell, node, 2) += f_minus(2) * refArea(cell, pt);
00193 
00194         } // end of pt
00195       } // end of numPlaneNodes
00196     } // end of cell
00197   }
00198   //----------------------------------------------------------------------------
00199 }

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