00001
00002
00003
00004
00005
00006 #include <Intrepid_MiniTensor.h>
00007 #include "Teuchos_TestForException.hpp"
00008 #include "Phalanx_DataLayout.hpp"
00009
00010 #include "Sacado_MathFunctions.hpp"
00011
00012 namespace LCM {
00013
00014
00015 template<typename EvalT, typename Traits>
00016 SurfaceBasis<EvalT, Traits>::SurfaceBasis(const Teuchos::ParameterList& p,
00017 const Teuchos::RCP<Albany::Layouts>& dl) :
00018 needCurrentBasis(false),
00019 referenceCoords(p.get<std::string>("Reference Coordinates Name"), dl->vertices_vector),
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 refBasis (p.get<std::string>("Reference Basis Name"), dl->qp_tensor),
00023 refArea (p.get<std::string>("Reference Area Name"), dl->qp_scalar),
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 {
00027 this->addDependentField(referenceCoords);
00028 this->addEvaluatedField(refBasis);
00029 this->addEvaluatedField(refArea);
00030 this->addEvaluatedField(refDualBasis);
00031 this->addEvaluatedField(refNormal);
00032
00033
00034
00035 if (p.isType<std::string>("Current Coordinates Name")) {
00036 needCurrentBasis = true;
00037
00038
00039 PHX::MDField<ScalarT, Cell, Vertex, Dim> tmp(p.get<std::string>("Current Coordinates Name"), dl->node_vector);
00040 currentCoords = tmp;
00041
00042
00043 PHX::MDField<ScalarT, Cell, QuadPoint, Dim, Dim> tmp2(p.get<std::string>("Current Basis Name"), dl->qp_tensor);
00044 currentBasis = tmp2;
00045
00046 this->addDependentField(currentCoords);
00047 this->addEvaluatedField(currentBasis);
00048 }
00049
00050
00051 std::vector<PHX::DataLayout::size_type> dims;
00052 dl->node_vector->dimensions(dims);
00053
00054 int containerSize = dims[0];
00055 numNodes = dims[1];
00056 numPlaneNodes = numNodes / 2;
00057
00058 numQPs = cubature->getNumPoints();
00059 numPlaneDims = cubature->getDimension();
00060 numDims = numPlaneDims + 1;
00061
00062 #ifdef ALBANY_VERBOSE
00063 std::cout << "in Surface Basis" << std::endl;
00064 std::cout << " numPlaneNodes: " << numPlaneNodes << std::endl;
00065 std::cout << " numPlaneDims: " << numPlaneDims << std::endl;
00066 std::cout << " numQPs: " << numQPs << std::endl;
00067 std::cout << " cubature->getNumPoints(): " << cubature->getNumPoints() << std::endl;
00068 std::cout << " cubature->getDimension(): " << cubature->getDimension() << std::endl;
00069 #endif
00070
00071
00072 refValues.resize(numPlaneNodes, numQPs);
00073 refGrads.resize(numPlaneNodes, numQPs, numPlaneDims);
00074 refPoints.resize(numQPs, numPlaneDims);
00075 refWeights.resize(numQPs);
00076
00077
00078 refMidplaneCoords.resize(containerSize, numPlaneNodes, numDims);
00079 currentMidplaneCoords.resize(containerSize, numPlaneNodes, numDims);
00080
00081
00082 cubature->getCubature(refPoints, refWeights);
00083 intrepidBasis->getValues(refValues, refPoints, Intrepid::OPERATOR_VALUE);
00084 intrepidBasis->getValues(refGrads, refPoints, Intrepid::OPERATOR_GRAD);
00085
00086 this->setName("SurfaceBasis" + PHX::TypeString<EvalT>::value);
00087 }
00088
00089
00090 template<typename EvalT, typename Traits>
00091 void SurfaceBasis<EvalT, Traits>::postRegistrationSetup(typename Traits::SetupData d, PHX::FieldManager<Traits>& fm)
00092 {
00093 this->utils.setFieldData(referenceCoords, fm);
00094 this->utils.setFieldData(refArea, fm);
00095 this->utils.setFieldData(refDualBasis, fm);
00096 this->utils.setFieldData(refNormal, fm);
00097 this->utils.setFieldData(refBasis, fm);
00098 if (needCurrentBasis) {
00099 this->utils.setFieldData(currentCoords, fm);
00100 this->utils.setFieldData(currentBasis, fm);
00101 }
00102 }
00103
00104
00105 template<typename EvalT, typename Traits>
00106 void SurfaceBasis<EvalT, Traits>::evaluateFields(typename Traits::EvalData workset)
00107 {
00108 for (std::size_t cell(0); cell < workset.numCells; ++cell) {
00109
00110
00111 computeReferenceMidplaneCoords(referenceCoords, refMidplaneCoords);
00112
00113
00114 computeReferenceBaseVectors(refMidplaneCoords, refBasis);
00115
00116
00117 computeDualBaseVectors(refMidplaneCoords, refBasis, refNormal, refDualBasis);
00118
00119
00120 computeJacobian(refBasis, refDualBasis, refArea);
00121
00122 if (needCurrentBasis) {
00123
00124
00125 computeCurrentMidplaneCoords(currentCoords, currentMidplaneCoords);
00126
00127
00128 computeCurrentBaseVectors(currentMidplaneCoords, currentBasis);
00129 }
00130 }
00131 }
00132
00133 template<typename EvalT, typename Traits>
00134 void SurfaceBasis<EvalT, Traits>::computeReferenceMidplaneCoords(PHX::MDField<MeshScalarT, Cell, Vertex, Dim> coords,
00135 MFC & midplaneCoords)
00136 {
00137 for (int cell(0); cell < midplaneCoords.dimension(0); ++cell) {
00138
00139 for (int node(0); node < numPlaneNodes; ++node) {
00140 int topNode = node + numPlaneNodes;
00141 for (int dim(0); dim < numDims; ++dim) {
00142 midplaneCoords(cell, node, dim) = 0.5 * (coords(cell, node, dim) + coords(cell, topNode, dim));
00143 }
00144 }
00145 }
00146 }
00147
00148 template<typename EvalT, typename Traits>
00149 void SurfaceBasis<EvalT, Traits>::computeCurrentMidplaneCoords(PHX::MDField<ScalarT, Cell, Vertex, Dim> coords,
00150 SFC & midplaneCoords)
00151 {
00152 for (int cell(0); cell < midplaneCoords.dimension(0); ++cell) {
00153
00154 for (int node(0); node < numPlaneNodes; ++node) {
00155 int topNode = node + numPlaneNodes;
00156 for (int dim(0); dim < numDims; ++dim) {
00157 midplaneCoords(cell, node, dim) = 0.5 * (coords(cell, node, dim) + coords(cell, topNode, dim));
00158 }
00159 }
00160 }
00161 }
00162
00163 template<typename EvalT, typename Traits>
00164 void SurfaceBasis<EvalT, Traits>::
00165 computeReferenceBaseVectors(const MFC & midplaneCoords,
00166 PHX::MDField<MeshScalarT, Cell, QuadPoint, Dim, Dim> basis)
00167 {
00168 for (int cell(0); cell < midplaneCoords.dimension(0); ++cell) {
00169
00170 std::vector<Intrepid::Vector<MeshScalarT> > midplaneNodes(numPlaneNodes);
00171 for (std::size_t node(0); node < numPlaneNodes; ++node)
00172 midplaneNodes[node] = Intrepid::Vector<MeshScalarT>(3, &midplaneCoords(cell, node, 0));
00173
00174 Intrepid::Vector<MeshScalarT> g_0(0, 0, 0), g_1(0, 0, 0), g_2(0, 0, 0);
00175
00176 for (std::size_t pt(0); pt < numQPs; ++pt) {
00177 g_0.clear();
00178 g_1.clear();
00179 g_2.clear();
00180 for (std::size_t node(0); node < numPlaneNodes; ++node) {
00181 g_0 += refGrads(node, pt, 0) * midplaneNodes[node];
00182 g_1 += refGrads(node, pt, 1) * midplaneNodes[node];
00183 }
00184 g_2 = cross(g_0, g_1) / norm(cross(g_0, g_1));
00185
00186 basis(cell, pt, 0, 0) = g_0(0);
00187 basis(cell, pt, 0, 1) = g_0(1);
00188 basis(cell, pt, 0, 2) = g_0(2);
00189 basis(cell, pt, 1, 0) = g_1(0);
00190 basis(cell, pt, 1, 1) = g_1(1);
00191 basis(cell, pt, 1, 2) = g_1(2);
00192 basis(cell, pt, 2, 0) = g_2(0);
00193 basis(cell, pt, 2, 1) = g_2(1);
00194 basis(cell, pt, 2, 2) = g_2(2);
00195 }
00196 }
00197 }
00198
00199 template<typename EvalT, typename Traits>
00200 void SurfaceBasis<EvalT, Traits>::
00201 computeCurrentBaseVectors(const SFC & midplaneCoords,
00202 PHX::MDField<ScalarT, Cell, QuadPoint, Dim, Dim> basis)
00203 {
00204 for (int cell(0); cell < midplaneCoords.dimension(0); ++cell) {
00205
00206 std::vector<Intrepid::Vector<ScalarT> > midplaneNodes(numPlaneNodes);
00207 for (std::size_t node(0); node < numPlaneNodes; ++node)
00208 midplaneNodes[node] = Intrepid::Vector<ScalarT>(3, &midplaneCoords(cell, node, 0));
00209
00210 Intrepid::Vector<ScalarT> g_0(0, 0, 0), g_1(0, 0, 0), g_2(0, 0, 0);
00211
00212 for (std::size_t pt(0); pt < numQPs; ++pt) {
00213 g_0.clear();
00214 g_1.clear();
00215 g_2.clear();
00216 for (std::size_t node(0); node < numPlaneNodes; ++node) {
00217 g_0 += refGrads(node, pt, 0) * midplaneNodes[node];
00218 g_1 += refGrads(node, pt, 1) * midplaneNodes[node];
00219 }
00220 g_2 = cross(g_0, g_1) / norm(cross(g_0, g_1));
00221
00222 basis(cell, pt, 0, 0) = g_0(0);
00223 basis(cell, pt, 0, 1) = g_0(1);
00224 basis(cell, pt, 0, 2) = g_0(2);
00225 basis(cell, pt, 1, 0) = g_1(0);
00226 basis(cell, pt, 1, 1) = g_1(1);
00227 basis(cell, pt, 1, 2) = g_1(2);
00228 basis(cell, pt, 2, 0) = g_2(0);
00229 basis(cell, pt, 2, 1) = g_2(1);
00230 basis(cell, pt, 2, 2) = g_2(2);
00231 }
00232 }
00233 }
00234
00235 template<typename EvalT, typename Traits>
00236 void SurfaceBasis<EvalT, Traits>::computeDualBaseVectors(
00237 const MFC & midplaneCoords,
00238 const PHX::MDField<MeshScalarT, Cell, QuadPoint, Dim, Dim> basis,
00239 PHX::MDField<MeshScalarT, Cell, QuadPoint, Dim> normal,
00240 PHX::MDField<MeshScalarT, Cell, QuadPoint, Dim, Dim> dualBasis)
00241 {
00242 std::size_t worksetSize = midplaneCoords.dimension(0);
00243
00244 Intrepid::Vector<MeshScalarT> g_0(0, 0, 0), g_1(0, 0, 0), g_2(0, 0, 0), g0(0, 0, 0),
00245 g1(0, 0, 0), g2(0, 0, 0);
00246
00247 for (std::size_t cell(0); cell < worksetSize; ++cell) {
00248 for (std::size_t pt(0); pt < numQPs; ++pt) {
00249 g_0 = Intrepid::Vector<MeshScalarT>(3, &basis(cell, pt, 0, 0));
00250 g_1 = Intrepid::Vector<MeshScalarT>(3, &basis(cell, pt, 1, 0));
00251 g_2 = Intrepid::Vector<MeshScalarT>(3, &basis(cell, pt, 2, 0));
00252
00253 normal(cell, pt, 0) = g_2(0);
00254 normal(cell, pt, 1) = g_2(1);
00255 normal(cell, pt, 2) = g_2(2);
00256
00257 g0 = cross(g_1, g_2) / dot(g_0, cross(g_1, g_2));
00258 g1 = cross(g_0, g_2) / dot(g_1, cross(g_0, g_2));
00259 g2 = cross(g_0, g_1) / dot(g_2, cross(g_0, g_1));
00260
00261 dualBasis(cell, pt, 0, 0) = g0(0);
00262 dualBasis(cell, pt, 0, 1) = g0(1);
00263 dualBasis(cell, pt, 0, 2) = g0(2);
00264 dualBasis(cell, pt, 1, 0) = g1(0);
00265 dualBasis(cell, pt, 1, 1) = g1(1);
00266 dualBasis(cell, pt, 1, 2) = g1(2);
00267 dualBasis(cell, pt, 2, 0) = g2(0);
00268 dualBasis(cell, pt, 2, 1) = g2(1);
00269 dualBasis(cell, pt, 2, 2) = g2(2);
00270 }
00271 }
00272 }
00273
00274 template<typename EvalT, typename Traits>
00275 void SurfaceBasis<EvalT, Traits>::computeJacobian(
00276 const PHX::MDField<MeshScalarT, Cell, QuadPoint, Dim, Dim> basis,
00277 const PHX::MDField<MeshScalarT, Cell, QuadPoint, Dim, Dim> dualBasis,
00278 PHX::MDField<MeshScalarT, Cell, QuadPoint> area)
00279 {
00280 const std::size_t worksetSize = basis.dimension(0);
00281
00282 for (std::size_t cell(0); cell < worksetSize; ++cell) {
00283 for (std::size_t pt(0); pt < numQPs; ++pt) {
00284 Intrepid::Tensor<MeshScalarT> dPhiInv(3, &dualBasis(cell, pt, 0, 0));
00285 Intrepid::Tensor<MeshScalarT> dPhi(3, &basis(cell, pt, 0, 0));
00286 Intrepid::Vector<MeshScalarT> G_2(3, &basis(cell, pt, 2, 0));
00287
00288 MeshScalarT j0 = Intrepid::det(dPhi);
00289 MeshScalarT jacobian = j0 *
00290 std::sqrt( Intrepid::dot(Intrepid::dot(G_2, Intrepid::transpose(dPhiInv) * dPhiInv), G_2));
00291 area(cell, pt) = jacobian * refWeights(pt);
00292 }
00293 }
00294
00295 }
00296
00297 }