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

PHAL_Neumann_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 #include <string>
00010 
00011 #include "Intrepid_FunctionSpaceTools.hpp"
00012 #include "Sacado_ParameterRegistration.hpp"
00013 
00014 //uncomment the following line if you want debug output to be printed to screen
00015 //#define OUTPUT_TO_SCREEN
00016 
00017 
00018 namespace PHAL {
00019 const double pi = 3.1415926535897932385;
00020 
00021 //**********************************************************************
00022 template<typename EvalT, typename Traits>
00023 NeumannBase<EvalT, Traits>::
00024 NeumannBase(const Teuchos::ParameterList& p) :
00025 
00026   dl             (p.get<Teuchos::RCP<Albany::Layouts> >("Layouts Struct")),
00027   meshSpecs      (p.get<Teuchos::RCP<Albany::MeshSpecsStruct> >("Mesh Specs Struct")),
00028   offset         (p.get<Teuchos::Array<int> >("Equation Offset")),
00029   sideSetID      (p.get<std::string>("Side Set ID")),
00030   coordVec       (p.get<std::string>("Coordinate Vector Name"), dl->vertices_vector)
00031 {
00032   // the input.xml string "NBC on SS sidelist_12 for DOF T set dudn" (or something like it)
00033   name = p.get< std::string >("Neumann Input String");
00034 
00035   // The input.xml argument for the above string
00036   inputValues = p.get<Teuchos::Array<double> >("Neumann Input Value");
00037 
00038   // The input.xml argument for the above string
00039   inputConditions = p.get< std::string >("Neumann Input Conditions");
00040 
00041   // The DOF offsets are contained in the Equation Offset array. The length of this array are the
00042   // number of DOFs we will set each call
00043   numDOFsSet = offset.size();
00044 
00045   // Set up values as parameters for parameter library
00046   Teuchos::RCP<ParamLib> paramLib = p.get< Teuchos::RCP<ParamLib> > ("Parameter Library");
00047 
00048   // If we are doing a Neumann internal boundary with a "scaled jump",
00049   // build a scale lookup table from the materialDB file (this must exist)
00050 
00051   int position;
00052 
00053   if((inputConditions == "scaled jump" || inputConditions == "robin") &&
00054      p.isType<Teuchos::RCP<QCAD::MaterialDatabase> >("MaterialDB")){
00055 
00057     Teuchos::RCP<QCAD::MaterialDatabase> materialDB =
00058       p.get< Teuchos::RCP<QCAD::MaterialDatabase> >("MaterialDB");
00059 
00060      // User has specified conditions on sideset normal
00061     if(inputConditions == "scaled jump") {
00062       bc_type = INTJUMP;
00063       const_val = inputValues[0];
00064       new Sacado::ParameterRegistration<EvalT, SPL_Traits> (name, this, paramLib);
00065     }
00066     else { // inputConditions == "robin"
00067       bc_type = ROBIN;
00068       robin_vals[0] = inputValues[0]; // dof_value
00069       robin_vals[1] = inputValues[1]; // coeff multiplying difference (dof - dof_value) -- could be permittivity/distance (distance in mesh units)
00070       robin_vals[2] = inputValues[2]; // jump in slope (like plain Neumann bc)
00071 
00072       for(int i = 0; i < 3; i++) {
00073         std::stringstream ss; ss << name << "[" << i << "]";
00074         new Sacado::ParameterRegistration<EvalT, SPL_Traits> (ss.str(), this, paramLib);
00075       }
00076     }
00077 
00078      // Build a vector to hold the scaling from the material DB
00079      matScaling.resize(meshSpecs->ebNameToIndex.size());
00080 
00081      // iterator over all ebnames in the mesh
00082 
00083      std::map<std::string, int>::const_iterator it;
00084      for(it = meshSpecs->ebNameToIndex.begin(); it != meshSpecs->ebNameToIndex.end(); it++){
00085 
00086 //      std::cout << "Searching for a value for \"Flux Scale\" in material database for element block: "
00087 //        << it->first << std::endl;
00088 
00089        TEUCHOS_TEST_FOR_EXCEPTION(!materialDB->isElementBlockParam(it->first, "Flux Scale"),
00090          Teuchos::Exceptions::InvalidParameter, "Cannot locate the value of \"Flux Scale\" for element block " 
00091           << it->first << " in the material database");
00092 
00093        matScaling[it->second] = 
00094          materialDB->getElementBlockParam<double>(it->first, "Flux Scale");
00095 
00096      }
00097 
00098 
00099      // In the robin boundary condition case, the NBC depends on the solution (dof) field
00100      if (inputConditions == "robin") {
00101       // Currently, the Neumann evaluator doesn't handle the case when the degree of freedom is a vector.
00102       // It wouldn't be difficult to have the boundary condition use a component of the vector, but I'm
00103       // not sure this is the correct behavior.  In any case, the only time when this evaluator needs
00104       // a degree of freedom value is in the "robin" case.
00105       TEUCHOS_TEST_FOR_EXCEPTION(p.get<bool>("Vector Field") == true, 
00106                Teuchos::Exceptions::InvalidParameter, 
00107                std::endl << "Error: \"Robin\" Neumann boundary conditions " 
00108            << "only supported when the DOF is not a vector" << std::endl);
00109 
00110        PHX::MDField<ScalarT,Cell,Node> tmp(p.get<std::string>("DOF Name"),
00111            p.get<Teuchos::RCP<PHX::DataLayout> >("DOF Data Layout"));
00112        dof = tmp;
00113 
00114        this->addDependentField(dof);
00115      }
00116   }
00117 
00118   // else parse the input to determine what type of BC to calculate
00119 
00120     // is there a "(" in the string?
00121   else if((position = inputConditions.find_first_of("(")) != std::string::npos){
00122 
00123       if(inputConditions.find("t_x", position + 1)){
00124         // User has specified conditions in base coords
00125         bc_type = TRACTION;
00126       }
00127       else {
00128         // User has specified conditions in base coords
00129         bc_type = COORD;
00130       }
00131 
00132       dudx.resize(meshSpecs->numDim);
00133       for(int i = 0; i < dudx.size(); i++)
00134         dudx[i] = inputValues[i];
00135 
00136       for(int i = 0; i < dudx.size(); i++) {
00137         std::stringstream ss; ss << name << "[" << i << "]";
00138         new Sacado::ParameterRegistration<EvalT, SPL_Traits> (ss.str(), this, paramLib);
00139       }
00140   }
00141   else if(inputConditions == "P"){ // Pressure boundary condition for Elasticity
00142 
00143       // User has specified a pressure condition
00144       bc_type = PRESS;
00145       const_val = inputValues[0];
00146       new Sacado::ParameterRegistration<EvalT, SPL_Traits> (name, this, paramLib);
00147 
00148   }
00149   else if(inputConditions == "basal"){ // Basal boundary condition for FELIX
00150 
00151       // User has specified alpha and beta to set BC d(flux)/dn = beta*u + alpha or d(flux)/dn = (alpha + beta1*x + beta2*y + beta3*sqrt(x*x+y*y))*u 
00152       bc_type = BASAL;
00153       robin_vals[0] = inputValues[0]; // beta
00154       robin_vals[1] = inputValues[1]; // alpha
00155       robin_vals[2] = inputValues[2]; // beta1
00156       robin_vals[3] = inputValues[3]; // beta2
00157       robin_vals[4] = inputValues[4]; // beta3
00158 
00159       for(int i = 0; i < 5; i++) {
00160         std::stringstream ss; ss << name << "[" << i << "]";
00161         new Sacado::ParameterRegistration<EvalT, SPL_Traits> (ss.str(), this, paramLib);
00162       }
00163        PHX::MDField<ScalarT,Cell,Node,VecDim> tmp(p.get<std::string>("DOF Name"),
00164            p.get<Teuchos::RCP<PHX::DataLayout> >("DOF Data Layout"));
00165        dofVec = tmp;
00166 #ifdef ALBANY_FELIX
00167       beta_field = PHX::MDField<ScalarT,Cell,Node>(
00168                     p.get<std::string>("Beta Field Name"), dl->node_scalar);
00169 #endif
00170      
00171       betaName = p.get<std::string>("BetaXY"); 
00172       L = p.get<double>("L"); 
00173 #ifdef OUTPUT_TO_SCREEN
00174       *out << "BetaName: " << betaName << std::endl; 
00175       *out << "L: " << L << std::endl;
00176 #endif
00177       if (betaName == "Constant") 
00178         beta_type = CONSTANT; 
00179       else if (betaName == "ExpTrig") 
00180         beta_type = EXPTRIG; 
00181       else if (betaName == "ISMIP-HOM Test C")
00182         beta_type = ISMIP_HOM_TEST_C;  
00183       else if (betaName == "ISMIP-HOM Test D")
00184         beta_type = ISMIP_HOM_TEST_D;  
00185       else if (betaName == "Confined Shelf")
00186         beta_type = CONFINEDSHELF;  
00187       else if (betaName == "Circular Shelf")
00188         beta_type = CIRCULARSHELF;  
00189       else if (betaName == "Dome UQ")
00190         beta_type = DOMEUQ;  
00191       else if (betaName == "Scalar Field")
00192         beta_type = SCALAR_FIELD;
00193 
00194       this->addDependentField(dofVec);
00195 #ifdef ALBANY_FELIX
00196       this->addDependentField(beta_field);
00197 #endif
00198   }
00199   else if(inputConditions == "lateral"){ // Basal boundary condition for FELIX
00200 
00201         // User has specified alpha and beta to set BC d(flux)/dn = beta*u + alpha or d(flux)/dn = (alpha + beta1*x + beta2*y + beta3*sqrt(x*x+y*y))*u
00202         bc_type = LATERAL;
00203         beta_type = LATERAL_BACKPRESSURE;
00204 
00205         for(int i = 0; i < 5; i++) {
00206           std::stringstream ss; ss << name << "[" << i << "]";
00207           new Sacado::ParameterRegistration<EvalT, SPL_Traits> (ss.str(), this, paramLib);
00208         }
00209          PHX::MDField<ScalarT,Cell,Node,VecDim> tmp(p.get<std::string>("DOF Name"),
00210              p.get<Teuchos::RCP<PHX::DataLayout> >("DOF Data Layout"));
00211          dofVec = tmp;
00212 #ifdef ALBANY_FELIX
00213        thickness_field = PHX::MDField<ScalarT,Cell,Node>(
00214                            p.get<std::string>("Thickness Field Name"), dl->node_scalar);
00215        elevation_field = PHX::MDField<RealType,Cell,Node>(
00216                            p.get<std::string>("Elevation Field Name"), dl->node_scalar);
00217         
00218         this->addDependentField(thickness_field);        
00219         this->addDependentField(elevation_field);
00220 #endif
00221 
00222         this->addDependentField(dofVec);
00223     }
00224 
00225   else {
00226 
00227       // User has specified conditions on sideset normal
00228       bc_type = NORMAL;
00229       const_val = inputValues[0];
00230       new Sacado::ParameterRegistration<EvalT, SPL_Traits> (name, this, paramLib);
00231 
00232   }
00233 
00234   this->addDependentField(coordVec);
00235 
00236   PHX::Tag<ScalarT> fieldTag(name, dl->dummy);
00237 
00238   this->addEvaluatedField(fieldTag);
00239 
00240   // Build element and side integration support
00241 
00242   const CellTopologyData * const elem_top = &meshSpecs->ctd;
00243 
00244   intrepidBasis = Albany::getIntrepidBasis(*elem_top);
00245 
00246   cellType = Teuchos::rcp(new shards::CellTopology (elem_top));
00247 
00248   Intrepid::DefaultCubatureFactory<RealType> cubFactory;
00249   cubatureCell = cubFactory.create(*cellType, meshSpecs->cubatureDegree);
00250 
00251   const CellTopologyData * const side_top = elem_top->side[0].topology;
00252 
00253   if(strncasecmp(side_top->name, "Line", 4) == 0)
00254 
00255     side_type = LINE;
00256 
00257   else if(strncasecmp(side_top->name, "Tri", 3) == 0)
00258 
00259     side_type = TRI;
00260 
00261   else if(strncasecmp(side_top->name, "Quad", 4) == 0)
00262 
00263     side_type = QUAD;
00264 
00265   else
00266 
00267       TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
00268              "PHAL_Neumann: side type : " << side_top->name << " is not supported." << std::endl);
00269 
00270 
00271   sideType = Teuchos::rcp(new shards::CellTopology(side_top)); 
00272   int cubatureDegree = (p.get<int>("Cubature Degree") > 0 ) ? p.get<int>("Cubature Degree") : meshSpecs->cubatureDegree;
00273   cubatureSide = cubFactory.create(*sideType, cubatureDegree);
00274 
00275   sideDims = sideType->getDimension();
00276   numQPsSide = cubatureSide->getNumPoints();
00277 
00278   numNodes = intrepidBasis->getCardinality();
00279 
00280   // Get Dimensions
00281   std::vector<PHX::DataLayout::size_type> dim;
00282   dl->qp_tensor->dimensions(dim);
00283   int containerSize = dim[0];
00284   numQPs = dim[1];
00285   cellDims = dim[2];
00286 
00287   // Allocate Temporary FieldContainers
00288   cubPointsSide.resize(numQPsSide, sideDims);
00289   refPointsSide.resize(numQPsSide, cellDims);
00290   cubWeightsSide.resize(numQPsSide);
00291   physPointsSide.resize(1, numQPsSide, cellDims);
00292   dofSide.resize(1, numQPsSide);
00293   dofSideVec.resize(1, numQPsSide, numDOFsSet);
00294 
00295   // Do the BC one side at a time for now
00296   jacobianSide.resize(1, numQPsSide, cellDims, cellDims);
00297   jacobianSide_det.resize(1, numQPsSide);
00298 
00299   weighted_measure.resize(1, numQPsSide);
00300   basis_refPointsSide.resize(numNodes, numQPsSide);
00301   trans_basis_refPointsSide.resize(1, numNodes, numQPsSide);
00302   weighted_trans_basis_refPointsSide.resize(1, numNodes, numQPsSide);
00303 
00304   physPointsCell.resize(1, numNodes, cellDims);
00305   dofCell.resize(1, numNodes);
00306   dofCellVec.resize(1, numNodes, numDOFsSet);
00307   neumann.resize(containerSize, numNodes, numDOFsSet);
00308   data.resize(1, numQPsSide, numDOFsSet);
00309 
00310   // Pre-Calculate reference element quantitites
00311   cubatureSide->getCubature(cubPointsSide, cubWeightsSide);
00312 
00313   this->setName(name+PHX::TypeString<EvalT>::value);
00314 
00315 }
00316 
00317 //**********************************************************************
00318 template<typename EvalT, typename Traits>
00319 void NeumannBase<EvalT, Traits>::
00320 postRegistrationSetup(typename Traits::SetupData d,
00321                       PHX::FieldManager<Traits>& fm)
00322 {
00323   this->utils.setFieldData(coordVec,fm);
00324   if (inputConditions == "robin") this->utils.setFieldData(dof,fm);
00325 #ifdef ALBANY_FELIX
00326   else if (inputConditions == "basal")
00327   {
00328     this->utils.setFieldData(dofVec,fm);
00329     this->utils.setFieldData(beta_field,fm);
00330   }
00331   else if(inputConditions == "lateral")
00332   {
00333     this->utils.setFieldData(dofVec,fm);
00334     this->utils.setFieldData(thickness_field,fm);
00335     this->utils.setFieldData(elevation_field,fm);
00336   }
00337 #endif
00338   // Note, we do not need to add dependent field to fm here for output - that is done
00339   // by Neumann Aggregator
00340 }
00341 
00342 template<typename EvalT, typename Traits>
00343 void NeumannBase<EvalT, Traits>::
00344 evaluateNeumannContribution(typename Traits::EvalData workset)
00345 {
00346 
00347   // setJacobian only needs to be RealType since the data type is only
00348   //  used internally for Basis Fns on reference elements, which are
00349   //  not functions of coordinates. This save 18min of compile time!!!
00350 
00351   // GAH: Note that this loosely follows from 
00352   // $TRILINOS_DIR/packages/intrepid/test/Discretization/Basis/HGRAD_QUAD_C1_FEM/test_02.cpp
00353 
00354   if(workset.sideSets == Teuchos::null || this->sideSetID.length() == 0)
00355 
00356     TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
00357          "Side sets defined in input file but not properly specified on the mesh" << std::endl);
00358 
00359 
00360   const Albany::SideSetList& ssList = *(workset.sideSets);
00361   Albany::SideSetList::const_iterator it = ssList.find(this->sideSetID);
00362 
00363   for (std::size_t cell=0; cell < workset.numCells; ++cell) 
00364    for (std::size_t node=0; node < numNodes; ++node)
00365      for (std::size_t dim=0; dim < numDOFsSet; ++dim)
00366        neumann(cell, node, dim) = 0.0;
00367 
00368   if(it == ssList.end()) return; // This sideset does not exist in this workset (GAH - this can go away
00369                                   // once we move logic to BCUtils
00370 
00371   const std::vector<Albany::SideStruct>& sideSet = it->second;
00372 
00373   Intrepid::FieldContainer<ScalarT> betaOnSide(1,numQPsSide);
00374   Intrepid::FieldContainer<ScalarT> thicknessOnSide(1,numQPsSide);
00375   Intrepid::FieldContainer<ScalarT> elevationOnSide(1,numQPsSide);
00376 
00377   // Loop over the sides that form the boundary condition 
00378 
00379   for (std::size_t side=0; side < sideSet.size(); ++side) { // loop over the sides on this ws and name
00380 
00381     // Get the data that corresponds to the side
00382 
00383     const int elem_GID = sideSet[side].elem_GID;
00384     const int elem_LID = sideSet[side].elem_LID;
00385     const int elem_side = sideSet[side].side_local_id;
00386 
00387     // Copy the coordinate data over to a temp container
00388 
00389     for (std::size_t node=0; node < numNodes; ++node)
00390       for (std::size_t dim=0; dim < cellDims; ++dim)
00391         physPointsCell(0, node, dim) = coordVec(elem_LID, node, dim);
00392 
00393 
00394     // Map side cubature points to the reference parent cell based on the appropriate side (elem_side) 
00395     Intrepid::CellTools<RealType>::mapToReferenceSubcell
00396       (refPointsSide, cubPointsSide, sideDims, elem_side, *cellType);
00397 
00398     // Calculate side geometry
00399     Intrepid::CellTools<RealType>::setJacobian
00400        (jacobianSide, refPointsSide, physPointsCell, *cellType);
00401 
00402     Intrepid::CellTools<MeshScalarT>::setJacobianDet(jacobianSide_det, jacobianSide);
00403 
00404     if (sideDims < 2) { //for 1 and 2D, get weighted edge measure 
00405       Intrepid::FunctionSpaceTools::computeEdgeMeasure<MeshScalarT>
00406         (weighted_measure, jacobianSide, cubWeightsSide, elem_side, *cellType);
00407     } 
00408     else { //for 3D, get weighted face measure 
00409       Intrepid::FunctionSpaceTools::computeFaceMeasure<MeshScalarT>
00410         (weighted_measure, jacobianSide, cubWeightsSide, elem_side, *cellType);
00411     }
00412 
00413     // Values of the basis functions at side cubature points, in the reference parent cell domain
00414     intrepidBasis->getValues(basis_refPointsSide, refPointsSide, Intrepid::OPERATOR_VALUE);
00415 
00416     // Transform values of the basis functions
00417     Intrepid::FunctionSpaceTools::HGRADtransformVALUE<RealType>
00418       (trans_basis_refPointsSide, basis_refPointsSide);
00419 
00420     // Multiply with weighted measure
00421     Intrepid::FunctionSpaceTools::multiplyMeasure<MeshScalarT>
00422       (weighted_trans_basis_refPointsSide, weighted_measure, trans_basis_refPointsSide);
00423 
00424     // Map cell (reference) cubature points to the appropriate side (elem_side) in physical space
00425     Intrepid::CellTools<RealType>::mapToPhysicalFrame
00426       (physPointsSide, refPointsSide, physPointsCell, *cellType);
00427 
00428     
00429     // Map cell (reference) degree of freedom points to the appropriate side (elem_side)
00430     if(bc_type == ROBIN) {
00431       for (std::size_t node=0; node < numNodes; ++node)
00432   dofCell(0, node) = dof(elem_LID, node);
00433 
00434       // This is needed, since evaluate currently sums into
00435       for (int i=0; i < numQPsSide ; i++) dofSide(0,i) = 0.0;
00436 
00437       // Get dof at cubature points of appropriate side (see DOFInterpolation evaluator)
00438       Intrepid::FunctionSpaceTools::
00439   evaluate<ScalarT>(dofSide, dofCell, trans_basis_refPointsSide);
00440     }
00441 
00442     // Map cell (reference) degree of freedom points to the appropriate side (elem_side)
00443     else if(bc_type == BASAL) {
00444       Intrepid::FieldContainer<ScalarT> betaOnCell(1, numNodes);
00445       for (std::size_t node=0; node < numNodes; ++node)
00446       {
00447       betaOnCell(0,node) = beta_field(elem_LID,node);
00448         for(int dim = 0; dim < numDOFsSet; dim++)
00449         dofCellVec(0,node,dim) = dofVec(elem_LID,node,this->offset[dim]);
00450       }
00451 
00452       // This is needed, since evaluate currently sums into
00453       for (int i=0; i < numQPsSide ; i++) betaOnSide(0,i) = 0.0;
00454       for (int i=0; i < dofSideVec.size() ; i++) dofSideVec[i] = 0.0;
00455 
00456       // Get dof at cubature points of appropriate side (see DOFVecInterpolation evaluator)
00457       for (std::size_t node=0; node < numNodes; ++node) { 
00458          for (std::size_t qp=0; qp < numQPsSide; ++qp) {
00459            betaOnSide(0, qp)  += betaOnCell(0, node) * trans_basis_refPointsSide(0, node, qp);
00460             for (int dim = 0; dim < numDOFsSet; dim++) {
00461                dofSideVec(0, qp, dim)  += dofCellVec(0, node, dim) * trans_basis_refPointsSide(0, node, qp); 
00462             }
00463           }
00464        }
00465 
00466       // Get dof at cubature points of appropriate side (see DOFVecInterpolation evaluator)
00467       //Intrepid::FunctionSpaceTools::
00468   //evaluate<ScalarT>(dofSide, dofCell, trans_basis_refPointsSide);
00469     }
00470 #ifdef ALBANY_FELIX
00471     else if(bc_type == LATERAL) {
00472       Intrepid::FieldContainer<ScalarT> thicknessOnCell(1, numNodes);
00473     Intrepid::FieldContainer<MeshScalarT> elevationOnCell(1, numNodes);
00474     for (std::size_t node=0; node < numNodes; ++node)
00475     {
00476     thicknessOnCell(0,node) = thickness_field(elem_LID,node);
00477     elevationOnCell(0,node) = elevation_field(elem_LID,node);
00478     for(int dim = 0; dim < numDOFsSet; dim++)
00479       dofCellVec(0,node,dim) = dofVec(elem_LID,node,this->offset[dim]);
00480     }
00481 
00482     // This is needed, since evaluate currently sums into
00483     for (int i=0; i < numQPsSide ; i++)
00484     {
00485       thicknessOnSide(0,i) = 0.0;
00486         elevationOnSide(0,i) = 0.0;
00487     }
00488     for (int i=0; i < dofSideVec.size() ; i++) dofSideVec[i] = 0.0;
00489 
00490     // Get dof at cubature points of appropriate side (see DOFVecInterpolation evaluator)
00491     for (std::size_t node=0; node < numNodes; ++node) {
00492      for (std::size_t qp=0; qp < numQPsSide; ++qp) {
00493        thicknessOnSide(0, qp)  += thicknessOnCell(0, node) * trans_basis_refPointsSide(0, node, qp);
00494        elevationOnSide(0, qp)  += elevationOnCell(0, node) * trans_basis_refPointsSide(0, node, qp);
00495       for (int dim = 0; dim < numDOFsSet; dim++) {
00496          dofSideVec(0, qp, dim)  += dofCellVec(0, node, dim) * trans_basis_refPointsSide(0, node, qp);
00497       }
00498       }
00499      }
00500 
00501     // Get dof at cubature points of appropriate side (see DOFVecInterpolation evaluator)
00502     //Intrepid::FunctionSpaceTools::
00503   //evaluate<ScalarT>(dofSide, dofCell, trans_basis_refPointsSide);
00504   }
00505 #endif
00506   // Transform the given BC data to the physical space QPs in each side (elem_side)
00507 
00508     switch(bc_type){
00509   
00510       case INTJUMP:
00511        {
00512          const ScalarT elem_scale = matScaling[sideSet[side].elem_ebIndex];
00513          calc_dudn_const(data, physPointsSide, jacobianSide, *cellType, cellDims, elem_side, elem_scale);
00514          break;
00515        }
00516 
00517       case ROBIN:
00518        {
00519          const ScalarT elem_scale = matScaling[sideSet[side].elem_ebIndex];
00520          calc_dudn_robin(data, physPointsSide, dofSide, jacobianSide, *cellType, cellDims, elem_side, elem_scale, robin_vals);
00521          break;
00522        }   
00523    
00524       case NORMAL:
00525   
00526          calc_dudn_const(data, physPointsSide, jacobianSide, *cellType, cellDims, elem_side);
00527          break;
00528 
00529       case PRESS:
00530   
00531          calc_press(data, physPointsSide, jacobianSide, *cellType, cellDims, elem_side);
00532          break;
00533       
00534       case BASAL:
00535 
00536 #ifdef ALBANY_FELIX
00537          calc_dudn_basal(data, betaOnSide, dofSideVec, jacobianSide, *cellType, cellDims, elem_side);
00538 
00539 #endif
00540          break;
00541 
00542       case LATERAL:
00543 
00544 #ifdef ALBANY_FELIX
00545        calc_dudn_lateral(data, thicknessOnSide, elevationOnSide, dofSideVec, jacobianSide, *cellType, cellDims, elem_side);
00546 
00547 #endif
00548        break;
00549       
00550       case TRACTION:
00551   
00552          calc_traction_components(data, physPointsSide, jacobianSide, *cellType, cellDims, elem_side);
00553          break;
00554       
00555       default:
00556   
00557          calc_gradu_dotn_const(data, physPointsSide, jacobianSide, *cellType, cellDims, elem_side);
00558          break;
00559   
00560     }
00561 
00562     // Put this side's contribution into the vector
00563 
00564     for (std::size_t node=0; node < numNodes; ++node)
00565       for (std::size_t qp=0; qp < numQPsSide; ++qp)
00566          for (std::size_t dim=0; dim < numDOFsSet; ++dim)
00567            neumann(elem_LID, node, dim) += 
00568                   data(0, qp, dim) * weighted_trans_basis_refPointsSide(0, node, qp);
00569 
00570 
00571   }
00572   
00573 }
00574 
00575 template<typename EvalT, typename Traits>
00576 typename NeumannBase<EvalT, Traits>::ScalarT&
00577 NeumannBase<EvalT, Traits>::
00578 getValue(const std::string &n) {
00579 
00580   if(std::string::npos != n.find("robin")) {
00581     for(int i = 0; i < 3; i++) {
00582       std::stringstream ss; ss << name << "[" << i << "]";
00583       if (n == ss.str())  return robin_vals[i];
00584     }
00585   }
00586   else if(std::string::npos != n.find("basal")) {
00587     for(int i = 0; i < 5; i++) {
00588       std::stringstream ss; ss << name << "[" << i << "]";
00589       if (n == ss.str())  return robin_vals[i];
00590     }
00591   }
00592   else {
00593     for(int i = 0; i < dudx.size(); i++) {
00594       std::stringstream ss; ss << name << "[" << i << "]";
00595       if (n == ss.str())  return dudx[i];
00596     }
00597   }
00598 
00599 //  if (n == name) return const_val;
00600   return const_val;
00601 
00602 }
00603 
00604 
00605 template<typename EvalT, typename Traits>
00606 void NeumannBase<EvalT, Traits>::
00607 calc_traction_components(Intrepid::FieldContainer<ScalarT> & qp_data_returned,
00608                           const Intrepid::FieldContainer<MeshScalarT>& phys_side_cub_points,
00609                           const Intrepid::FieldContainer<MeshScalarT>& jacobian_side_refcell,
00610                           const shards::CellTopology & celltopo,
00611                           const int cellDims,
00612                           int local_side_id){
00613 
00614   int numCells = qp_data_returned.dimension(0); // How many cell's worth of data is being computed?
00615   int numPoints = qp_data_returned.dimension(1); // How many QPs per cell?
00616   int numDOFs = qp_data_returned.dimension(2); // How many DOFs per node to calculate?
00617 
00618   Intrepid::FieldContainer<ScalarT> traction(numCells, numPoints, cellDims);
00619 
00620 /*
00621   double traction[3];
00622   traction[0] = 1.0; // x component of traction
00623   traction[1] = 0.0; // y component of traction
00624   traction[2] = 0.0; // z component of traction
00625 */
00626 
00627   for(int cell = 0; cell < numCells; cell++)
00628     for(int pt = 0; pt < numPoints; pt++)
00629       for(int dim = 0; dim < cellDims; dim++)
00630         traction(cell, pt, dim) = dudx[dim]; 
00631 
00632   for(int pt = 0; pt < numPoints; pt++)
00633     for(int dim = 0; dim < numDOFsSet; dim++)
00634       qp_data_returned(0, pt, dim) = -traction(0, pt, dim);
00635 
00636 }
00637 
00638 template<typename EvalT, typename Traits>
00639 void NeumannBase<EvalT, Traits>::
00640 calc_gradu_dotn_const(Intrepid::FieldContainer<ScalarT> & qp_data_returned,
00641                           const Intrepid::FieldContainer<MeshScalarT>& phys_side_cub_points,
00642                           const Intrepid::FieldContainer<MeshScalarT>& jacobian_side_refcell,
00643                           const shards::CellTopology & celltopo,
00644                           const int cellDims,
00645                           int local_side_id){
00646 
00647   int numCells = qp_data_returned.dimension(0); // How many cell's worth of data is being computed?
00648   int numPoints = qp_data_returned.dimension(1); // How many QPs per cell?
00649   int numDOFs = qp_data_returned.dimension(2); // How many DOFs per node to calculate?
00650 
00651   Intrepid::FieldContainer<ScalarT> grad_T(numCells, numPoints, cellDims);
00652   Intrepid::FieldContainer<MeshScalarT> side_normals(numCells, numPoints, cellDims);
00653   Intrepid::FieldContainer<MeshScalarT> normal_lengths(numCells, numPoints);
00654 
00655 /*
00656   double kdTdx[3];
00657   kdTdx[0] = 1.0; // Neumann component in the x direction
00658   kdTdx[1] = 0.0; // Neumann component in the y direction
00659   kdTdx[2] = 0.0; // Neumann component in the z direction
00660 */
00661 
00662   for(int cell = 0; cell < numCells; cell++)
00663     for(int pt = 0; pt < numPoints; pt++)
00664       for(int dim = 0; dim < cellDims; dim++)
00665         grad_T(cell, pt, dim) = dudx[dim]; // k grad T in the x direction goes in the x spot, and so on
00666 
00667   // for this side in the reference cell, get the components of the normal direction vector
00668   Intrepid::CellTools<MeshScalarT>::getPhysicalSideNormals(side_normals, jacobian_side_refcell, 
00669     local_side_id, celltopo);
00670 
00671   // scale normals (unity)
00672   Intrepid::RealSpaceTools<MeshScalarT>::vectorNorm(normal_lengths, side_normals, Intrepid::NORM_TWO);
00673   Intrepid::FunctionSpaceTools::scalarMultiplyDataData<MeshScalarT>(side_normals, normal_lengths, 
00674     side_normals, true);
00675 
00676   // take grad_T dotted with the unit normal
00677 //  Intrepid::FunctionSpaceTools::dotMultiplyDataData<ScalarT>(qp_data_returned, 
00678 //    grad_T, side_normals);
00679 
00680   for(int pt = 0; pt < numPoints; pt++)
00681     for(int dim = 0; dim < numDOFsSet; dim++)
00682       qp_data_returned(0, pt, dim) = grad_T(0, pt, dim) * side_normals(0, pt, dim);
00683 
00684 }
00685 
00686 template<typename EvalT, typename Traits>
00687 void NeumannBase<EvalT, Traits>::
00688 calc_dudn_const(Intrepid::FieldContainer<ScalarT> & qp_data_returned,
00689                           const Intrepid::FieldContainer<MeshScalarT>& phys_side_cub_points,
00690                           const Intrepid::FieldContainer<MeshScalarT>& jacobian_side_refcell,
00691                           const shards::CellTopology & celltopo,
00692                           const int cellDims,
00693                           int local_side_id,
00694                           ScalarT scale){
00695 
00696   int numCells = qp_data_returned.dimension(0); // How many cell's worth of data is being computed?
00697   int numPoints = qp_data_returned.dimension(1); // How many QPs per cell?
00698   int numDOFs = qp_data_returned.dimension(2); // How many DOFs per node to calculate?
00699 
00700   //std::cout << "DEBUG: applying const dudn to sideset " << this->sideSetID << ": " << (const_val * scale) << std::endl;
00701 
00702   for(int pt = 0; pt < numPoints; pt++)
00703     for(int dim = 0; dim < numDOFsSet; dim++)
00704       qp_data_returned(0, pt, dim) = -const_val * scale; // User directly specified dTdn, just use it
00705 
00706 
00707 }
00708 
00709 template<typename EvalT, typename Traits>
00710 void NeumannBase<EvalT, Traits>::
00711 calc_dudn_robin(Intrepid::FieldContainer<ScalarT> & qp_data_returned,
00712     const Intrepid::FieldContainer<MeshScalarT>& phys_side_cub_points,
00713     const Intrepid::FieldContainer<ScalarT>& dof_side,
00714     const Intrepid::FieldContainer<MeshScalarT>& jacobian_side_refcell,
00715     const shards::CellTopology & celltopo,
00716     const int cellDims,
00717     int local_side_id,
00718     ScalarT scale,
00719     const ScalarT* robin_param_values){
00720 
00721   int numCells = qp_data_returned.dimension(0); // How many cell's worth of data is being computed?
00722   int numPoints = qp_data_returned.dimension(1); // How many QPs per cell?
00723   int numDOFs = qp_data_returned.dimension(2); // How many DOFs per node to calculate?
00724 
00725   const ScalarT& dof_value = robin_vals[0];
00726   const ScalarT& coeff = robin_vals[1];
00727   const ScalarT& jump = robin_vals[2];
00728 
00729   for(int pt = 0; pt < numPoints; pt++)
00730     for(int dim = 0; dim < numDOFsSet; dim++)
00731       qp_data_returned(0, pt, dim) = coeff*(dof_side(0,pt) - dof_value) - jump * scale * 2.0; 
00732          // mult by 2 to emulate behavior of an internal side within a single material (element block) 
00733          //  in which case usual Neumann would add contributions from both sides, giving factor of 2
00734 }
00735 
00736 
00737 template<typename EvalT, typename Traits>
00738 void NeumannBase<EvalT, Traits>::
00739 calc_press(Intrepid::FieldContainer<ScalarT> & qp_data_returned,
00740                           const Intrepid::FieldContainer<MeshScalarT>& phys_side_cub_points,
00741                           const Intrepid::FieldContainer<MeshScalarT>& jacobian_side_refcell,
00742                           const shards::CellTopology & celltopo,
00743                           const int cellDims,
00744                           int local_side_id){
00745 
00746   int numCells = qp_data_returned.dimension(0); // How many cell's worth of data is being computed?
00747   int numPoints = qp_data_returned.dimension(1); // How many QPs per cell?
00748   int numDOFs = qp_data_returned.dimension(2); // How many DOFs per node to calculate?
00749 
00750   Intrepid::FieldContainer<MeshScalarT> side_normals(numCells, numPoints, cellDims);
00751   Intrepid::FieldContainer<MeshScalarT> normal_lengths(numCells, numPoints);
00752   Intrepid::FieldContainer<MeshScalarT> ref_normal(cellDims);
00753 
00754   // for this side in the reference cell, get the components of the normal direction vector
00755   Intrepid::CellTools<MeshScalarT>::getPhysicalSideNormals(side_normals, jacobian_side_refcell, 
00756     local_side_id, celltopo);
00757 
00758   // for this side in the reference cell, get the constant normal vector to the side for area calc
00759   Intrepid::CellTools<MeshScalarT>::getReferenceSideNormal(ref_normal, local_side_id, celltopo);
00760   /* Note: if the side is 1D the length of the normal times 2 is the side length
00761      If the side is a 2D quad, the length of the normal is the area of the side
00762      If the side is a 2D triangle, the length of the normal times 1/2 is the area of the side
00763    */
00764 
00765   MeshScalarT area = 
00766     Intrepid::RealSpaceTools<MeshScalarT>::vectorNorm(ref_normal, Intrepid::NORM_TWO);
00767 
00768   // Calculate proper areas
00769 
00770   switch(side_type){
00771 
00772     case LINE:
00773 
00774       area *= 2;
00775       break;
00776 
00777     case TRI:
00778 
00779       area /= 2;
00780       break;
00781 
00782     case QUAD:
00783 
00784       break;
00785 
00786     default:
00787       TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
00788              "Need to supply area function for boundary type: " << side_type << std::endl);
00789       break;
00790 
00791   }
00792 
00793   // scale normals (unity)
00794   Intrepid::RealSpaceTools<MeshScalarT>::vectorNorm(normal_lengths, side_normals, Intrepid::NORM_TWO);
00795   Intrepid::FunctionSpaceTools::scalarMultiplyDataData<MeshScalarT>(side_normals, normal_lengths, 
00796     side_normals, true);
00797 
00798   // Pressure is a force of magnitude P along the normal to the side, divided by the side area (det)
00799 
00800   for(int cell = 0; cell < numCells; cell++)
00801     for(int pt = 0; pt < numPoints; pt++)
00802       for(int dim = 0; dim < numDOFsSet; dim++)
00803 //        qp_data_returned(cell, pt, dim) = const_val * side_normals(cell, pt, dim);
00804         qp_data_returned(cell, pt, dim) = const_val * side_normals(cell, pt, dim) / area;
00805 
00806 
00807 }
00808 
00809 
00810 #ifdef ALBANY_FELIX
00811 template<typename EvalT, typename Traits>
00812 void NeumannBase<EvalT, Traits>::
00813 calc_dudn_basal(Intrepid::FieldContainer<ScalarT> & qp_data_returned,
00814                         const Intrepid::FieldContainer<ScalarT>& basalFriction_side,
00815                         const Intrepid::FieldContainer<ScalarT>& dof_side,
00816                           const Intrepid::FieldContainer<MeshScalarT>& jacobian_side_refcell,
00817                           const shards::CellTopology & celltopo,
00818                           const int cellDims,
00819                           int local_side_id){
00820 
00821   int numCells = qp_data_returned.dimension(0); // How many cell's worth of data is being computed?
00822   int numPoints = qp_data_returned.dimension(1); // How many QPs per cell?
00823   int numDOFs = qp_data_returned.dimension(2); // How many DOFs per node to calculate?
00824 
00825   //std::cout << "DEBUG: applying const dudn to sideset " << this->sideSetID << ": " << (const_val * scale) << std::endl;
00826 
00827   const ScalarT& beta = robin_vals[0];
00828   const ScalarT& alpha = robin_vals[1];
00829   const ScalarT& beta1 = robin_vals[2];
00830   const ScalarT& beta2 = robin_vals[3];
00831   const ScalarT& beta3 = robin_vals[4];
00832   
00833   Intrepid::FieldContainer<MeshScalarT> side_normals(numCells, numPoints, cellDims);
00834   Intrepid::FieldContainer<MeshScalarT> normal_lengths(numCells, numPoints);
00835 
00836   // for this side in the reference cell, get the components of the normal direction vector
00837   Intrepid::CellTools<MeshScalarT>::getPhysicalSideNormals(side_normals, jacobian_side_refcell, 
00838     local_side_id, celltopo);
00839   
00840   // scale normals (unity)
00841   Intrepid::RealSpaceTools<MeshScalarT>::vectorNorm(normal_lengths, side_normals, Intrepid::NORM_TWO);
00842   Intrepid::FunctionSpaceTools::scalarMultiplyDataData<MeshScalarT>(side_normals, normal_lengths, 
00843     side_normals, true);
00844  
00845   const double a = 1.0;
00846   const double Atmp = 1.0;
00847   const double ntmp = 3.0;   
00848   if (beta_type == CONSTANT) {//basal (robin) condition indepenent of space
00849     betaXY = 1.0; 
00850     for(int cell = 0; cell < numCells; cell++) { 
00851       for(int pt = 0; pt < numPoints; pt++) {
00852         for(int dim = 0; dim < numDOFsSet; dim++) {
00853           qp_data_returned(cell, pt, dim) = betaXY*beta*dof_side(cell, pt,dim) - alpha; // d(stress)/dn = beta*u + alpha
00854         }
00855       }
00856     }
00857   }
00858   if (beta_type == SCALAR_FIELD) {//basal (robin) condition indepenent of space
00859       betaXY = 1.0;
00860       for(int cell = 0; cell < numCells; cell++) {
00861         for(int pt = 0; pt < numPoints; pt++) {
00862           for(int dim = 0; dim < numDOFsSet; dim++) {
00863             qp_data_returned(cell, pt, dim) = betaXY*basalFriction_side(cell, pt)*dof_side(cell, pt,dim); // d(stress)/dn = beta*u + alpha
00864           }
00865         }
00866       }
00867   }
00868   else if (beta_type == EXPTRIG) {  
00869     const double a = 1.0; 
00870     const double A = 1.0; 
00871     const double n = L; 
00872     for(int cell = 0; cell < numCells; cell++) { 
00873       for(int pt = 0; pt < numPoints; pt++) {
00874         for(int dim = 0; dim < numDOFsSet; dim++) {
00875           MeshScalarT x = physPointsSide(cell,pt,0);
00876           MeshScalarT y2pi = 2.0*pi*physPointsSide(cell,pt,1);
00877           MeshScalarT muargt = (a*a + 4.0*pi*pi - 2.0*pi*a)*sin(y2pi)*sin(y2pi) + 1.0/4.0*(2.0*pi+a)*(2.0*pi+a)*cos(y2pi)*cos(y2pi); 
00878           muargt = sqrt(muargt)*exp(a*x);  
00879           betaXY = 1.0/2.0*pow(A, -1.0/n)*pow(muargt, 1.0/n - 1.0);
00880           qp_data_returned(cell, pt, dim) = betaXY*beta*dof_side(cell, pt,dim) - alpha*side_normals(cell,pt,dim); // d(stress)/dn = beta*u + alpha
00881         }
00882       }
00883   }
00884  }
00885  else if (beta_type == ISMIP_HOM_TEST_C) { 
00886     for(int cell = 0; cell < numCells; cell++) { 
00887       for(int pt = 0; pt < numPoints; pt++) {
00888         for(int dim = 0; dim < numDOFsSet; dim++) {
00889           MeshScalarT x = physPointsSide(cell,pt,0);
00890           MeshScalarT y = physPointsSide(cell,pt,1);
00891           betaXY = 1.0 + sin(2.0*pi/L*x)*sin(2.0*pi/L*y); 
00892           qp_data_returned(cell, pt, dim) = betaXY*beta*dof_side(cell, pt,dim) - alpha*side_normals(cell,pt,dim); // d(stress)/dn = beta*u + alpha
00893         }
00894       }
00895   }
00896  }
00897  else if (beta_type == ISMIP_HOM_TEST_D) { 
00898     for(int cell = 0; cell < numCells; cell++) { 
00899       for(int pt = 0; pt < numPoints; pt++) {
00900         for(int dim = 0; dim < numDOFsSet; dim++) {
00901           MeshScalarT x = physPointsSide(cell,pt,0);
00902           betaXY = 1.0 + sin(2.0*pi/L*x); 
00903           qp_data_returned(cell, pt, dim) = betaXY*beta*dof_side(cell, pt,dim) - alpha*side_normals(cell,pt,dim); // d(stress)/dn = beta*u + alpha
00904         }
00905       }
00906   }
00907  }
00908  else if (beta_type == CONFINEDSHELF) {
00909     const double s = 0.06; 
00910     for(int cell = 0; cell < numCells; cell++) { 
00911       for(int pt = 0; pt < numPoints; pt++) {
00912         for(int dim = 0; dim < numDOFsSet; dim++) {
00913           MeshScalarT z = physPointsSide(cell,pt,2);
00914           if (z > 0.0) 
00915             betaXY = 0.0;
00916           else 
00917             betaXY = -z; //betaXY = depth in km
00918           qp_data_returned(cell, pt, dim) = -(beta*(s-z) + alpha*betaXY); // d(stress)/dn = beta*(s-z)+alpha*(-z)
00919         }
00920       }
00921   }
00922  }
00923  else if (beta_type == CIRCULARSHELF) {
00924     const double s = 0.11479;  
00925     for(int cell = 0; cell < numCells; cell++) { 
00926       for(int pt = 0; pt < numPoints; pt++) {
00927         for(int dim = 0; dim < numDOFsSet; dim++) {
00928           MeshScalarT z = physPointsSide(cell,pt,2);
00929           if (z > 0.0) 
00930             betaXY = 0.0;
00931           else 
00932             betaXY = -z; //betaXY = depth in km
00933           qp_data_returned(cell, pt, dim) = -(beta*(s-z) + alpha*betaXY)*side_normals(cell,pt,dim); // d(stress)/dn = (beta*(s-z)+alpha*(-z))*n_i
00934         }
00935       }
00936   }
00937  }
00938  else if (beta_type == DOMEUQ) {
00939     for(int cell = 0; cell < numCells; cell++) { 
00940       for(int pt = 0; pt < numPoints; pt++) {
00941         for(int dim = 0; dim < numDOFsSet; dim++) {
00942           MeshScalarT x = physPointsSide(cell,pt,0);
00943           MeshScalarT y = physPointsSide(cell,pt,1);
00944           MeshScalarT r = sqrt(x*x+y*y); 
00945           qp_data_returned(cell, pt, dim) = (alpha + beta1*x + beta2*y + beta3*r)*dof_side(cell,pt,dim); // d(stress)/dn = (alpha + beta1*x + beta2*y + beta3*r)*u; 
00946         }
00947       }
00948   }
00949  }
00950 
00951 
00952 }
00953 
00954 
00955 template<typename EvalT, typename Traits>
00956 void NeumannBase<EvalT, Traits>::
00957 calc_dudn_lateral(Intrepid::FieldContainer<ScalarT> & qp_data_returned,
00958                         const Intrepid::FieldContainer<ScalarT>& thickness_side,
00959                         const Intrepid::FieldContainer<ScalarT>& elevation_side,
00960                         const Intrepid::FieldContainer<ScalarT>& dof_side,
00961                           const Intrepid::FieldContainer<MeshScalarT>& jacobian_side_refcell,
00962                           const shards::CellTopology & celltopo,
00963                           const int cellDims,
00964                           int local_side_id){
00965 
00966   int numCells = qp_data_returned.dimension(0); // How many cell's worth of data is being computed?
00967   int numPoints = qp_data_returned.dimension(1); // How many QPs per cell?
00968 
00969   //std::cout << "DEBUG: applying const dudn to sideset " << this->sideSetID << ": " << (const_val * scale) << std::endl;
00970 
00971   Intrepid::FieldContainer<MeshScalarT> side_normals(numCells, numPoints, cellDims);
00972   Intrepid::FieldContainer<MeshScalarT> normal_lengths(numCells, numPoints);
00973 
00974   // for this side in the reference cell, get the components of the normal direction vector
00975   Intrepid::CellTools<MeshScalarT>::getPhysicalSideNormals(side_normals, jacobian_side_refcell,
00976     local_side_id, celltopo);
00977 
00978   // scale normals (unity)
00979   Intrepid::RealSpaceTools<MeshScalarT>::vectorNorm(normal_lengths, side_normals, Intrepid::NORM_TWO);
00980   Intrepid::FunctionSpaceTools::scalarMultiplyDataData<MeshScalarT>(side_normals, normal_lengths,
00981     side_normals, true);
00982 
00983   if (beta_type == LATERAL_BACKPRESSURE)
00984   {
00985     const double g = 9.8;
00986     const double rho = 910;
00987     const double rho_w = 1028;
00988     for(int cell = 0; cell < numCells; cell++) {
00989     for(int pt = 0; pt < numPoints; pt++) {
00990       ScalarT H = thickness_side(cell, pt);
00991       ScalarT s = elevation_side(cell, pt);
00992       ScalarT immersedRatio = 0.;
00993       if(H > 1e-8) //make sure H is not too small
00994       {
00995         ScalarT ratio = s/H;
00996         if(ratio < 0.)          //ice is completely under sea level
00997           immersedRatio = 1;
00998         else if(ratio < 1)      //ice is partially under sea level
00999           immersedRatio = 1. - ratio;
01000       }
01001       ScalarT normalStress = - 0.5 * g *  H * (rho - rho_w * immersedRatio*immersedRatio);
01002 
01003       for(int dim = 0; dim < numDOFsSet; dim++)
01004         qp_data_returned(cell, pt, dim) =  normalStress * side_normals(cell,pt,dim);
01005 
01006     }
01007       }
01008     }
01009   }
01010 
01011 #endif
01012 
01013 // **********************************************************************
01014 // Specialization: Residual
01015 // **********************************************************************
01016 template<typename Traits>
01017 Neumann<PHAL::AlbanyTraits::Residual,Traits>::
01018 Neumann(Teuchos::ParameterList& p)
01019   : NeumannBase<PHAL::AlbanyTraits::Residual,Traits>(p)
01020 {
01021 }
01022 
01023 template<typename Traits>
01024 void Neumann<PHAL::AlbanyTraits::Residual, Traits>::
01025 evaluateFields(typename Traits::EvalData workset)
01026 {
01027 
01028   Teuchos::RCP<Epetra_Vector> f = workset.f;
01029   ScalarT *valptr;
01030 
01031   // Fill in "neumann" array
01032   this->evaluateNeumannContribution(workset);
01033 
01034   // Place it at the appropriate offset into F
01035   for (std::size_t cell=0; cell < workset.numCells; ++cell ) {
01036     const Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> >& nodeID  = workset.wsElNodeEqID[cell];
01037 
01038 
01039     for (std::size_t node = 0; node < this->numNodes; ++node)
01040       for (std::size_t dim = 0; dim < this->numDOFsSet; ++dim){
01041 
01042         valptr = &(this->neumann)(cell, node, dim);
01043         (*f)[nodeID[node][this->offset[dim]]] += *valptr;
01044 
01045     }
01046   }
01047 }
01048 
01049 // **********************************************************************
01050 // Specialization: Jacobian
01051 // **********************************************************************
01052 
01053 template<typename Traits>
01054 Neumann<PHAL::AlbanyTraits::Jacobian, Traits>::
01055 Neumann(Teuchos::ParameterList& p)
01056   : NeumannBase<PHAL::AlbanyTraits::Jacobian,Traits>(p)
01057 {
01058 }
01059 
01060 // **********************************************************************
01061 template<typename Traits>
01062 void Neumann<PHAL::AlbanyTraits::Jacobian, Traits>::
01063 evaluateFields(typename Traits::EvalData workset)
01064 {
01065   Teuchos::RCP<Epetra_Vector> f = workset.f;
01066   Teuchos::RCP<Epetra_CrsMatrix> Jac = workset.Jac;
01067   ScalarT *valptr;
01068 
01069   // Fill in "neumann" array
01070   this->evaluateNeumannContribution(workset);
01071 
01072   int row, lcol, col;
01073 
01074   for (std::size_t cell=0; cell < workset.numCells; ++cell ) {
01075     const Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> >& nodeID  = workset.wsElNodeEqID[cell];
01076 
01077     for (std::size_t node = 0; node < this->numNodes; ++node)
01078       for (std::size_t dim = 0; dim < this->numDOFsSet; ++dim){
01079      
01080         valptr = &(this->neumann)(cell, node, dim);
01081 
01082         row = nodeID[node][this->offset[dim]];
01083         int neq = nodeID[node].size();
01084 
01085         if (f != Teuchos::null) 
01086           f->SumIntoMyValue(row, 0, valptr->val());
01087 
01088         // Check derivative array is nonzero
01089         if (valptr->hasFastAccess()) {
01090 
01091           // Loop over nodes in element
01092           for (unsigned int node_col=0; node_col<this->numNodes; node_col++){
01093 
01094             // Loop over equations per node
01095             for (unsigned int eq_col=0; eq_col<neq; eq_col++) {
01096               lcol = neq * node_col + eq_col;
01097 
01098               // Global column
01099               col =  nodeID[node_col][eq_col];
01100               
01101               if (workset.is_adjoint) {
01102                 // Sum Jacobian transposed
01103                 Jac->SumIntoMyValues(col, 1, &(valptr->fastAccessDx(lcol)), &row);
01104               }
01105               else {
01106                 // Sum Jacobian
01107                 Jac->SumIntoMyValues(row, 1, &(valptr->fastAccessDx(lcol)), &col);
01108               }
01109             } // column equations
01110           } // column nodes
01111         } // has fast access
01112     }
01113   }
01114 }
01115 
01116 // **********************************************************************
01117 // Specialization: Tangent
01118 // **********************************************************************
01119 
01120 template<typename Traits>
01121 Neumann<PHAL::AlbanyTraits::Tangent, Traits>::
01122 Neumann(Teuchos::ParameterList& p)
01123   : NeumannBase<PHAL::AlbanyTraits::Tangent,Traits>(p)
01124 {
01125 }
01126 
01127 // **********************************************************************
01128 template<typename Traits>
01129 void Neumann<PHAL::AlbanyTraits::Tangent, Traits>::
01130 evaluateFields(typename Traits::EvalData workset)
01131 {
01132   Teuchos::RCP<Epetra_Vector> f = workset.f;
01133   Teuchos::RCP<Epetra_MultiVector> JV = workset.JV;
01134   Teuchos::RCP<Epetra_MultiVector> fp = workset.fp;
01135   ScalarT *valptr;
01136 
01137   const Epetra_BlockMap *row_map = NULL;
01138 
01139   if (f != Teuchos::null)
01140     row_map = &(f->Map());
01141   else if (JV != Teuchos::null)
01142     row_map = &(JV->Map());
01143   else if (fp != Teuchos::null)
01144     row_map = &(fp->Map());
01145   else
01146     TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01147                      "One of f, JV, or fp must be non-null! " << std::endl);
01148 
01149   // Fill the local "neumann" array with cell contributions
01150 
01151   this->evaluateNeumannContribution(workset);
01152 
01153   for (std::size_t cell=0; cell < workset.numCells; ++cell ) {
01154     const Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> >& nodeID  = workset.wsElNodeEqID[cell];
01155 
01156     for (std::size_t node = 0; node < this->numNodes; ++node) 
01157       for (std::size_t dim = 0; dim < this->numDOFsSet; ++dim){
01158 
01159         valptr = &(this->neumann)(cell, node, dim);
01160 
01161         int row = nodeID[node][this->offset[dim]];
01162 
01163         if (f != Teuchos::null)
01164           f->SumIntoMyValue(row, 0, valptr->val());
01165 
01166         if (JV != Teuchos::null)
01167           for (int col=0; col<workset.num_cols_x; col++)
01168 
01169         JV->SumIntoMyValue(row, col, valptr->dx(col));
01170 
01171         if (fp != Teuchos::null)
01172           for (int col=0; col<workset.num_cols_p; col++)
01173             fp->SumIntoMyValue(row, col, valptr->dx(col+workset.param_offset));
01174       }
01175   }
01176 }
01177 
01178 // **********************************************************************
01179 // Specialization: Stochastic Galerkin Residual
01180 // **********************************************************************
01181 
01182 #ifdef ALBANY_SG_MP
01183 template<typename Traits>
01184 Neumann<PHAL::AlbanyTraits::SGResidual, Traits>::
01185 Neumann(Teuchos::ParameterList& p)
01186   : NeumannBase<PHAL::AlbanyTraits::SGResidual,Traits>(p)
01187 {
01188 }
01189 
01190 
01191 // **********************************************************************
01192 template<typename Traits>
01193 void Neumann<PHAL::AlbanyTraits::SGResidual, Traits>::
01194 evaluateFields(typename Traits::EvalData workset)
01195 {
01196 
01197   Teuchos::RCP< Stokhos::EpetraVectorOrthogPoly > f = workset.sg_f;
01198   ScalarT *valptr;
01199 
01200   int nblock = f->size();
01201 
01202   // Fill the local "neumann" array with cell contributions
01203 
01204   this->evaluateNeumannContribution(workset);
01205 
01206   for (std::size_t cell=0; cell < workset.numCells; ++cell ) {
01207     const Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> >& nodeID  = workset.wsElNodeEqID[cell];
01208 
01209     for (std::size_t node = 0; node < this->numNodes; ++node) 
01210       for (std::size_t dim = 0; dim < this->numDOFsSet; ++dim){
01211 
01212         valptr = &(this->neumann)(cell, node, dim);
01213 
01214         for (int block=0; block<nblock; block++)
01215             (*f)[block][nodeID[node][this->offset[dim]]] += valptr->coeff(block);
01216 
01217     }
01218   }
01219 }
01220 
01221 // **********************************************************************
01222 // Specialization: Stochastic Galerkin Jacobian
01223 // **********************************************************************
01224 
01225 template<typename Traits>
01226 Neumann<PHAL::AlbanyTraits::SGJacobian, Traits>::
01227 Neumann(Teuchos::ParameterList& p)
01228   : NeumannBase<PHAL::AlbanyTraits::SGJacobian,Traits>(p)
01229 {
01230 }
01231 
01232 // **********************************************************************
01233 template<typename Traits>
01234 void Neumann<PHAL::AlbanyTraits::SGJacobian, Traits>::
01235 evaluateFields(typename Traits::EvalData workset)
01236 {
01237   Teuchos::RCP< Stokhos::EpetraVectorOrthogPoly > f = workset.sg_f;
01238   Teuchos::RCP< Stokhos::VectorOrthogPoly<Epetra_CrsMatrix> > Jac = 
01239     workset.sg_Jac;
01240   ScalarT *valptr;
01241 
01242   // Fill the local "neumann" array with cell contributions
01243 
01244   this->evaluateNeumannContribution(workset);
01245 
01246   int row, lcol, col;
01247   int nblock = 0;
01248 
01249   if (f != Teuchos::null)
01250     nblock = f->size();
01251 
01252   int nblock_jac = Jac->size();
01253   double c; // use double since it goes into CrsMatrix
01254 
01255   for (std::size_t cell=0; cell < workset.numCells; ++cell ) {
01256     const Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> >& nodeID  = workset.wsElNodeEqID[cell];
01257 
01258     for (std::size_t node = 0; node < this->numNodes; ++node)
01259       for (std::size_t dim = 0; dim < this->numDOFsSet; ++dim){
01260 
01261         valptr = &(this->neumann)(cell, node, dim);
01262 
01263         row = nodeID[node][this->offset[dim]];
01264         int neq = nodeID[node].size();
01265 
01266         if (f != Teuchos::null) {
01267 
01268           for (int block=0; block<nblock; block++)
01269             (*f)[block].SumIntoMyValue(row, 0, valptr->val().coeff(block));
01270 
01271         }
01272 
01273         // Check derivative array is nonzero
01274         if (valptr->hasFastAccess()) {
01275 
01276           // Loop over nodes in element
01277           for (unsigned int node_col=0; node_col<this->numNodes; node_col++){
01278 
01279             // Loop over equations per node
01280             for (unsigned int eq_col=0; eq_col<neq; eq_col++) {
01281               lcol = neq * node_col + eq_col;
01282 
01283               // Global column
01284               col =  nodeID[node_col][eq_col];
01285 
01286               // Sum Jacobian
01287               for (int block=0; block<nblock_jac; block++) {
01288 
01289                 c = valptr->fastAccessDx(lcol).coeff(block);
01290                 if (workset.is_adjoint) { 
01291 
01292                   (*Jac)[block].SumIntoMyValues(col, 1, &c, &row);
01293 
01294                 }
01295                 else {
01296 
01297                   (*Jac)[block].SumIntoMyValues(row, 1, &c, &col);
01298 
01299                 }
01300               }
01301             } // column equations
01302           } // column nodes
01303         } // has fast access
01304     }
01305   }
01306 }
01307 
01308 // **********************************************************************
01309 // Specialization: Stochastic Galerkin Tangent
01310 // **********************************************************************
01311 
01312 template<typename Traits>
01313 Neumann<PHAL::AlbanyTraits::SGTangent, Traits>::
01314 Neumann(Teuchos::ParameterList& p)
01315   : NeumannBase<PHAL::AlbanyTraits::SGTangent,Traits>(p)
01316 {
01317 }
01318 
01319 // **********************************************************************
01320 template<typename Traits>
01321 void Neumann<PHAL::AlbanyTraits::SGTangent, Traits>::
01322 evaluateFields(typename Traits::EvalData workset)
01323 {
01324   Teuchos::RCP< Stokhos::EpetraVectorOrthogPoly > f = workset.sg_f;
01325   Teuchos::RCP< Stokhos::EpetraMultiVectorOrthogPoly > JV = workset.sg_JV;
01326   Teuchos::RCP< Stokhos::EpetraMultiVectorOrthogPoly > fp = workset.sg_fp;
01327   ScalarT *valptr;
01328 
01329   // Fill the local "neumann" array with cell contributions
01330 
01331   this->evaluateNeumannContribution(workset);
01332 
01333   int nblock = 0;
01334   if (f != Teuchos::null)
01335     nblock = f->size();
01336   else if (JV != Teuchos::null)
01337     nblock = JV->size();
01338   else if (fp != Teuchos::null)
01339     nblock = fp->size();
01340   else
01341     TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01342            "One of sg_f, sg_JV, or sg_fp must be non-null! " << 
01343            std::endl);
01344 
01345   for (std::size_t cell=0; cell < workset.numCells; ++cell ) {
01346 
01347     const Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> >& nodeID  = workset.wsElNodeEqID[cell];
01348 
01349     for (std::size_t node = 0; node < this->numNodes; ++node)
01350       for (std::size_t dim = 0; dim < this->numDOFsSet; ++dim){
01351 
01352         valptr = &(this->neumann)(cell, node, dim);
01353 
01354         int row = nodeID[node][this->offset[dim]];
01355 
01356         if (f != Teuchos::null)
01357           for (int block=0; block<nblock; block++)
01358             (*f)[block].SumIntoMyValue(row, 0, valptr->val().coeff(block));
01359 
01360         if (JV != Teuchos::null)
01361           for (int col=0; col<workset.num_cols_x; col++)
01362             for (int block=0; block<nblock; block++)
01363               (*JV)[block].SumIntoMyValue(row, col, valptr->dx(col).coeff(block));
01364 
01365           for (int col=0; col<workset.num_cols_p; col++)
01366             for (int block=0; block<nblock; block++)
01367               (*fp)[block].SumIntoMyValue(row, col, valptr->dx(col+workset.param_offset).coeff(block));
01368     }
01369   }
01370 }
01371 
01372 // **********************************************************************
01373 // Specialization: Multi-point Residual
01374 // **********************************************************************
01375 
01376 template<typename Traits>
01377 Neumann<PHAL::AlbanyTraits::MPResidual, Traits>::
01378 Neumann(Teuchos::ParameterList& p)
01379   : NeumannBase<PHAL::AlbanyTraits::MPResidual,Traits>(p)
01380 {
01381 }
01382 
01383 // **********************************************************************
01384 template<typename Traits>
01385 void Neumann<PHAL::AlbanyTraits::MPResidual, Traits>::
01386 evaluateFields(typename Traits::EvalData workset)
01387 {
01388   Teuchos::RCP< Stokhos::ProductEpetraVector > f = workset.mp_f;
01389   ScalarT *valptr;
01390 
01391   // Fill the local "neumann" array with cell contributions
01392 
01393   this->evaluateNeumannContribution(workset);
01394 
01395   int nblock = f->size();
01396   for (std::size_t cell=0; cell < workset.numCells; ++cell ) {
01397     const Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> >& nodeID  = workset.wsElNodeEqID[cell];
01398 
01399     for (std::size_t node = 0; node < this->numNodes; ++node) 
01400       for (std::size_t dim = 0; dim < this->numDOFsSet; ++dim){
01401 
01402         valptr = &(this->neumann)(cell, node, dim);
01403 
01404         for (int block=0; block<nblock; block++)
01405           (*f)[block][nodeID[node][this->offset[dim]]] += valptr->coeff(block);
01406 
01407     }
01408   }
01409 }
01410 
01411 // **********************************************************************
01412 // Specialization: Multi-point Jacobian
01413 // **********************************************************************
01414 
01415 template<typename Traits>
01416 Neumann<PHAL::AlbanyTraits::MPJacobian, Traits>::
01417 Neumann(Teuchos::ParameterList& p)
01418   : NeumannBase<PHAL::AlbanyTraits::MPJacobian,Traits>(p)
01419 {
01420 }
01421 
01422 // **********************************************************************
01423 template<typename Traits>
01424 void Neumann<PHAL::AlbanyTraits::MPJacobian, Traits>::
01425 evaluateFields(typename Traits::EvalData workset)
01426 {
01427   Teuchos::RCP< Stokhos::ProductEpetraVector > f = workset.mp_f;
01428   Teuchos::RCP< Stokhos::ProductContainer<Epetra_CrsMatrix> > Jac = 
01429     workset.mp_Jac;
01430   ScalarT *valptr;
01431 
01432   // Fill the local "neumann" array with cell contributions
01433 
01434   this->evaluateNeumannContribution(workset);
01435 
01436   int row, lcol, col;
01437   int nblock = 0;
01438 
01439   if (f != Teuchos::null)
01440     nblock = f->size();
01441 
01442   int nblock_jac = Jac->size();
01443   double c; // use double since it goes into CrsMatrix
01444 
01445   for (std::size_t cell=0; cell < workset.numCells; ++cell ) {
01446     const Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> >& nodeID  = workset.wsElNodeEqID[cell];
01447 
01448     for (std::size_t node = 0; node < this->numNodes; ++node) 
01449       for (std::size_t dim = 0; dim < this->numDOFsSet; ++dim){
01450 
01451         valptr = &(this->neumann)(cell, node, dim);
01452 
01453         row = nodeID[node][this->offset[dim]];
01454         int neq = nodeID[node].size();
01455 
01456         if (f != Teuchos::null) 
01457           for (int block=0; block<nblock; block++)
01458             (*f)[block].SumIntoMyValue(row, 0, valptr->val().coeff(block));
01459 
01460 
01461         // Check derivative array is nonzero
01462         if (valptr->hasFastAccess()) {
01463 
01464           // Loop over nodes in element
01465           for (unsigned int node_col=0; node_col<this->numNodes; node_col++){
01466 
01467             // Loop over equations per node
01468             for (unsigned int eq_col=0; eq_col<neq; eq_col++) {
01469               lcol = neq * node_col + eq_col;
01470 
01471               // Global column
01472               col =  nodeID[node_col][eq_col];
01473 
01474               // Sum Jacobian
01475               for (int block=0; block<nblock_jac; block++) {
01476 
01477                 c = valptr->fastAccessDx(lcol).coeff(block);
01478                (*Jac)[block].SumIntoMyValues(row, 1, &c, &col);
01479 
01480              }
01481             } // column equations
01482           } // column nodes
01483         } // has fast access
01484     }
01485   }
01486 }
01487 
01488 // **********************************************************************
01489 // Specialization: Multi-point Tangent
01490 // **********************************************************************
01491 
01492 template<typename Traits>
01493 Neumann<PHAL::AlbanyTraits::MPTangent, Traits>::
01494 Neumann(Teuchos::ParameterList& p)
01495   : NeumannBase<PHAL::AlbanyTraits::MPTangent,Traits>(p)
01496 {
01497 }
01498 
01499 // **********************************************************************
01500 template<typename Traits>
01501 void Neumann<PHAL::AlbanyTraits::MPTangent, Traits>::
01502 evaluateFields(typename Traits::EvalData workset)
01503 {
01504   Teuchos::RCP< Stokhos::ProductEpetraVector > f = workset.mp_f;
01505   Teuchos::RCP< Stokhos::ProductEpetraMultiVector > JV = workset.mp_JV;
01506   Teuchos::RCP< Stokhos::ProductEpetraMultiVector > fp = workset.mp_fp;
01507   ScalarT *valptr;
01508 
01509   // Fill the local "neumann" array with cell contributions
01510 
01511   this->evaluateNeumannContribution(workset);
01512 
01513   int nblock = 0;
01514   if (f != Teuchos::null)
01515     nblock = f->size();
01516   else if (JV != Teuchos::null)
01517     nblock = JV->size();
01518   else if (fp != Teuchos::null)
01519     nblock = fp->size();
01520   else
01521     TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01522            "One of mp_f, mp_JV, or mp_fp must be non-null! " << 
01523            std::endl);
01524 
01525   for (std::size_t cell=0; cell < workset.numCells; ++cell ) {
01526     const Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> >& nodeID  = workset.wsElNodeEqID[cell];
01527 
01528     for (std::size_t node = 0; node < this->numNodes; ++node)
01529       for (std::size_t dim = 0; dim < this->numDOFsSet; ++dim){
01530 
01531         valptr = &(this->neumann)(cell, node, dim);
01532 
01533         int row = nodeID[node][this->offset[dim]];
01534 
01535         if (f != Teuchos::null)
01536           for (int block=0; block<nblock; block++)
01537             (*f)[block].SumIntoMyValue(row, 0, valptr->val().coeff(block));
01538 
01539         if (JV != Teuchos::null)
01540           for (int col=0; col<workset.num_cols_x; col++)
01541             for (int block=0; block<nblock; block++)
01542               (*JV)[block].SumIntoMyValue(row, col, valptr->dx(col).coeff(block));
01543 
01544         if (fp != Teuchos::null)
01545           for (int col=0; col<workset.num_cols_p; col++)
01546             for (int block=0; block<nblock; block++)
01547               (*fp)[block].SumIntoMyValue(row, col, valptr->dx(col+workset.param_offset).coeff(block));
01548 
01549     }
01550   }
01551 }
01552 #endif //ALBANY_SG_MP
01553 
01554 
01555 // **********************************************************************
01556 // Simple evaluator to aggregate all Neumann BCs into one "field"
01557 // **********************************************************************
01558 
01559 template<typename EvalT, typename Traits>
01560 NeumannAggregator<EvalT, Traits>::
01561 NeumannAggregator(const Teuchos::ParameterList& p) 
01562 {
01563   Teuchos::RCP<PHX::DataLayout> dl =  p.get< Teuchos::RCP<PHX::DataLayout> >("Data Layout");
01564 
01565   std::vector<std::string>& nbcs = *(p.get<std::vector<std::string>* >("NBC Names"));
01566 
01567   for (unsigned int i=0; i<nbcs.size(); i++) {
01568     PHX::Tag<ScalarT> fieldTag(nbcs[i], dl);
01569     this->addDependentField(fieldTag);
01570   }
01571 
01572   PHX::Tag<ScalarT> fieldTag(p.get<std::string>("NBC Aggregator Name"), dl);
01573   this->addEvaluatedField(fieldTag);
01574 
01575   this->setName("Neumann Aggregator"+PHX::TypeString<EvalT>::value);
01576 }
01577 
01578 //**********************************************************************
01579 }

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