00001
00002
00003
00004
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
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
00061 refValues.resize(numPlaneNodes, numQPs);
00062 refGrads.resize(numPlaneNodes, numQPs, numPlaneDims);
00063 refPoints.resize(numQPs, numPlaneDims);
00064 refWeights.resize(numQPs);
00065
00066
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
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
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
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
00121 Intrepid::Vector<ScalarT> g_0(3, ¤tBasis(cell, pt, 0, 0));
00122 Intrepid::Vector<ScalarT> g_1(3, ¤tBasis(cell, pt, 1, 0));
00123 Intrepid::Vector<ScalarT> n(3, ¤tBasis(cell, pt, 2, 0));
00124
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
00129 Intrepid::Vector<MeshScalarT> N(3, &refNormal(cell, pt, 0));
00130
00131
00132 f_plus.clear();
00133 f_minus.clear();
00134
00135
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
00152 tmp1 = 0.5 * I(m,i) * ( refGrads(node, pt, 0) * G0(L) +
00153 refGrads(node, pt, 1) * G1(L) );
00154
00155
00156 dndxbar = 0.0;
00157 for (int r(0); r < numDims; ++r) {
00158 for (int s(0); s < numDims; ++s) {
00159
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
00170 dFdx_plus = tmp1 + tmp2;
00171
00172
00173 dFdx_minus = tmp1 + tmp2;
00174
00175
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
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 }
00195 }
00196 }
00197 }
00198
00199 }